Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Введение.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
5 Мб
Скачать
☆
  1. Заключение.

В ходе проделанной работы было создано простейшее игровое 2D приложение. Главная цель курсового проекта и задачи, поставленные изначально, были успешно выполнены. Проект можно назвать полноценным игровым приложением, которое имеет дальнейшие перспективы усовершенствования. Основные перспективы:

  1. Возможность пользователя отключать звук во время игры.

  2. Наличие нескольких уровней.

  3. Возможность пользователя вводить свое имя перед началом игры.

  4. Возможность пользователя сравнивать свой результат с результатами предыдущих прохождений.

  5. Доработка графической составляющей (усовершенствование графики).

  6. Возможность пользователя выбирать внешний вид персонажа, карту для прохождения и уровень сложности.

  7. Добавление сюжетной канвы.

  8. Нелинейность уровней.

  9. Скелетная анимация.

  10. Подключение мыши.

5. Приложения.

    1. Полный код программы.

#include <SFML/Graphics.hpp>

#include <SFML/Audio.hpp>

#include <iostream>

#include <vector>

#include <list>

#include "string.h"

#include <stdio.h>

#include <sstream>//преобразование int в string

#include <string>

#include <windows.h>

#include "level.hpp"

#include "anim.hpp"

using namespace sf;

bool ingame=0,newgame=1,reit=0,esc=0,reite=0;

std::string ress,ress2,winn;

int res=0,reset,buf=100,win=100;

static inline std::string int2Str(int x)

{

std::stringstream type;

type << x;

return type.str();

}

class Entity

{

public:

float x,y,dx,dy,w,h;

AnimationManager anim;

std::vector<Object> obj;

bool life, dir;

float timer, timer_end;

String Name;

int Health;

Entity(AnimationManager &A,int X, int Y)

{

anim = A;

x = X;

y = Y;

dir = 0;

life=true;

timer=0;

timer_end=0;

dx=dy=0;

}

virtual void update(float time) = 0;

void draw(RenderWindow &window)

{

anim.draw(window,x,y+h);

}

FloatRect getRect()

{

return FloatRect(x,y,w,h);

}

void option(String NAME, float SPEED=0, int HEALTH=10, String FIRST_ANIM="")

{

Name = NAME;

if (FIRST_ANIM!="") anim.set(FIRST_ANIM);

w = anim.getW();

h = anim.getH();

dx = SPEED;

Health = HEALTH;

}

};

class Bullet:public Entity

{

public:

Bullet(AnimationManager &a, Level &lev,int x,int y,bool dir):Entity(a,x,y)

{

option("Bullet", 0.3, 10, "move");

if (dir) dx=-0.3;

obj = lev.GetObjects("solid");

}

void update(float time)

{

x+=dx*time;

for (int i=0;i<obj.size();i++)

if (getRect().intersects(obj[i].rect))

{Health=0;}

if (Health<=0) {anim.set("explode");dx=0;

if (anim.isPlaying()==false) life=false;

}

anim.tick(time);

}

};

class PLAYER: public Entity

{

public:

enum {stay,walk,duck,jump,climb,swim} STATE;

bool onLadder, shoot, hit;

std::map<std::string,bool> key;

PLAYER(AnimationManager &a, Level &lev,int x,int y):Entity(a,x,y)

{

option("Player",0,100,"stay");

STATE=stay; hit=0;

obj = lev.GetAllObjects();

}

void KeyCheck()

{

if (key["L"])

{

dir=1;

if (STATE!=duck) dx=-0.1;

if (STATE==stay) STATE=walk;

}

if (key["R"])

{

dir=0;

if (STATE!=duck) dx=0.1;

if (STATE==stay) STATE=walk;

}

if (key["Up"])

{

if (onLadder) STATE=climb;

if (STATE==stay || STATE==walk) { dy=-0.27; STATE=jump; anim.play("jump");}

if (STATE==swim || STATE==climb) dy=-0.05;

}

if (key["Down"])

{

if (STATE==stay || STATE==walk) { STATE=duck; dx=0;}

if (STATE==swim || STATE==climb) dy=0.05;

}

if (key["Space"])

{

shoot=true;

}

/////////////////////если клавиша отпущена///////////////////////////

if (!(key["R"] || key["L"]))

{

dx=0;

if (STATE==walk) STATE=stay;

}

if (!(key["Up"] || key["Down"]))

{

if (STATE==swim || STATE==climb) dy=0;

}

if (!key["Down"])

{

if (STATE==duck) { STATE=stay;}

}

if (!key["Space"])

{

shoot=false;

}

}

void update(float time)

{

KeyCheck();

if (STATE==stay) anim.set("stay");

if (STATE==walk) anim.set("walk");

if (STATE==jump) anim.set("jump");

if (STATE==duck) anim.set("duck");

if (STATE==climb) {anim.set("climb"); anim.pause(); if (dy!=0) anim.play(); if (!onLadder) STATE=stay;}

if (shoot) { anim.set("shoot");

if (STATE==walk) anim.set("shootAndWalk");}

if (hit) { timer+=time;

if (timer>1000) {hit=false; timer=0;}

anim.set("hit");}

if (dir) anim.flip();

x += dx * time;

Collision(0);

if (STATE!=climb) dy+=0.0005*time;

y += dy*time; onLadder=false;

Collision(1);

anim.tick(time);

key["R"]=key["L"]=key["Up"]=key["Down"]=key["Space"]=false;

}

void Collision(int num)

{

for (int i=0;i<obj.size();i++)

if (getRect().intersects(obj[i].rect))

{ if(obj[i].name=="do")

{

}

if(obj[i].name=="trap")

{

hit=1;

Health-=1;

}

if (obj[i].name=="solid")

{

if (dy>0 && num==1) { y = obj[i].rect.top - h; dy=0; STATE=stay;}

if (dy<0 && num==1) { y = obj[i].rect.top + obj[i].rect.height ; dy=0;}

if (dx>0 && num==0) { x = obj[i].rect.left - w; }

if (dx<0 && num==0) { x = obj[i].rect.left + obj[i].rect.width ;}

}

if (obj[i].name=="ladder") { onLadder=true; }

if (obj[i].name=="SlopeLeft")

{ FloatRect r = obj[i].rect;

int y0 = (x+w/2-r.left) * r.height/r.width+ r.top - h;

if (y>y0)

if (x+w/2>r.left)

{y = y0; dy=0; STATE=stay;}

}

if (obj[i].name=="SlopeRight")

{ FloatRect r = obj[i].rect;

int y0 = - (x+w/2-r.left) * r.height/r.width + r.top+r.height - h;

if (y > y0)

if (x+w/2<r.left+r.width)

{y = y0 ; dy=0; STATE=stay;}

}

}

}

};

class ENEMY: public Entity

{

public:

ENEMY(AnimationManager &a, Level &lev,int x,int y):Entity(a,x,y)

{

option("Enemy", 0.01, 15, "move");

}

void update(float time)

{

x += dx * time;

timer+=time;

if (timer>3200) {dx*=-1;timer=0;}

if (Health<=0) {anim.set("dead"); dx=0;

timer_end+=time;

if (timer_end>4000) life=false;

}

anim.tick(time);

}

};

class COIN: public Entity

{

public:

COIN(AnimationManager &a, Level &lev,int x,int y):Entity(a,x,y)

{

option("Coin", 0, 1, "move");

}

void update(float time)

{

x += dx * time;

timer+=time;

if (timer>3200) {dx*=-1;timer=0;}

if (Health<=0) {anim.set("dead"); dx=0;

timer_end+=time;

if (timer_end>4000) life=false;

}

anim.tick(time);

}

};

class MovingPlatform: public Entity

{

public:

MovingPlatform(AnimationManager &a, Level &lev,int x,int y):Entity(a,x,y)

{

option("MovingPlatform", 0.05, 0, "move");

}

void update(float time)

{

x += dx * time;

timer+=time;

if (timer>6000) {dx*=-1;timer=0;}

anim.tick(time);

}

};

int main()

{

Music music,jump,shoot,hit,enter,change;

jump.openFromFile("files/jump.wav");

shoot.openFromFile("files/shoot.wav");

music.openFromFile("files/main.wav");

hit.openFromFile("files/hit.wav");

enter.openFromFile("files/enter.wav");

change.openFromFile("files/change.wav");

Text text,//новая игра

text2,//результаты

text3,//выход

text4,//очки на экран

text5,//гейм овер

text6,//жизнь на экран

text7,//жизнь

text8,//about

text9,//win

text10,// /

text11,//управление

text12;//about выбрано

Font font;

font.loadFromFile("sansation.ttf");

text.setFont(font);

text.setString("New Game");

text.setCharacterSize(24);

text2.setFont(font);

text2.setString("Coin:");

text2.setCharacterSize(24);

text3.setFont(font);

text3.setString("Exit");

text3.setCharacterSize(24);

text4.setFont(font);

text4.setCharacterSize(24);

text5.setFont(font);

text5.setString("Game");

text5.setCharacterSize(24);

text6.setFont(font);

text6.setCharacterSize(24);

text7.setFont(font);

text7.setCharacterSize(24);

text7.setString("Health:");

text8.setFont(font);

text8.setCharacterSize(24);

text8.setString("About");

text9.setFont(font);

text9.setCharacterSize(24);

text10.setFont(font);

text10.setCharacterSize(24);

text10.setString("/");

text11.setFont(font);

text11.setCharacterSize(24);

text11.setString("Press [E] to select\nUse [W][A][S][D] to move\nPress [space] to shoot\nPress [Esc] to return to menu");

text12.setFont(font);

text12.setCharacterSize(24);

text12.setString("Was created by Antonova Evgenia\n Mashukow Nikolay");

///////////// инициализация ///////////////////////////

RenderWindow window(VideoMode(1280, 720), "My Game");

Style::None;

pro1:

View view( FloatRect(0, 0, 1280, 720) );

Level lvl;

lvl.LoadFromFile("level.tmx");

Texture tileSet, moveplatform, megaman, fang,coinn,menu,pict;

Sprite menuspr,pictspr;

menu.loadFromFile("files/menu.png");

menuspr.setTexture(menu);

menuspr.setTextureRect(IntRect(0,0,1280,720));

pict.loadFromFile("files/ingame.png");

pictspr.setTexture(pict);

pictspr.setTextureRect(IntRect(0,0,1280,720));

tileSet.loadFromFile("files/enemy.png");

moveplatform.loadFromFile("files/movingPlatform.png");

megaman.loadFromFile("files//megaman.png");

fang.loadFromFile("files/bullet.png");

coinn.loadFromFile("files/coin.png");

AnimationManager anim;

anim.loadFromXML("files/megaman_anim.xml",megaman);

anim.animList["jump"].loop = 0;

AnimationManager anim2;

anim2.create("move",fang,16,0,16,4,1,0);

anim2.create("explode",fang,6,0,16,16,4,0.01,29,false);

AnimationManager anim3;

anim3.create("move",tileSet,0,0,32,32,2,0.002,32);

anim3.create("dead",tileSet,64,0,32,32,2,0.0005,32);

AnimationManager anim4;

anim4.create("move",moveplatform,0,0,95,22,1,0);

AnimationManager anim5;

anim5.create("move",coinn,0,0,32,32,2,0.002,32);

anim5.create("dead",coinn,64,0,32,32,2,0.0005,32);

std::list<Entity*> entities;

std::list<Entity*>::iterator it;

std::vector<Object> e;

e= lvl.GetObjects("enemy");

for (int i=0;i < e.size();i++)

entities.push_back(new ENEMY(anim3, lvl, e[i].rect.left, e[i].rect.top) );

e = lvl.GetObjects("MovingPlatform");

for (int i=0;i < e.size();i++)

entities.push_back(new MovingPlatform(anim4, lvl, e[i].rect.left, e[i].rect.top) );

e = lvl.GetObjects("Coin");

for (int i=0;i < e.size();i++)

entities.push_back(new COIN(anim5, lvl, e[i].rect.left, e[i].rect.top) );

win=e.size();

Object pl = lvl.GetObject("player");

PLAYER player1(anim, lvl, pl.rect.left, pl.rect.top);

music.play();

Clock clock;

Clock musicc;

/////////////////// основной цикл /////////////////////

while (window.isOpen())

{

ress=int2Str(res);

winn=int2Str(win);

ress2=int2Str(player1.Health);

text4.setString(ress);

text6.setString(ress2);

text9.setString(winn);

float time = clock.getElapsedTime().asMicroseconds();

float musiccc=musicc.getElapsedTime().asSeconds();

clock.restart();

time = time/600;

if (time > 400) time = 400;

if(musiccc>=10)

{

music.play();

musicc.restart();

}

Event event;

while (window.pollEvent(event))

{

if (event.type == Event::Closed)

window.close();

if(ingame==0)

{

if (event.type == Event::KeyPressed)

if (event.key.code==Keyboard::Escape)

window.close();

if(newgame==1)

{

if (event.type == Event::KeyPressed)

if (event.key.code==Keyboard::E)

{ enter.play();

res=0;

ingame=1;

reset=0;

text5.setCharacterSize(24);

}

}

if(esc)

{

if (event.type == Event::KeyPressed)

if (event.key.code==Keyboard::E)

{

window.close();

enter.play();

}

}

}

if (event.type == Event::KeyPressed)

if (event.key.code==Keyboard::Space)

{entities.push_back(new Bullet(anim2,lvl,player1.x+18,player1.y+18,player1.dir) ); shoot.play(); }

}

if(ingame==1)

{

if (Keyboard::isKeyPressed(Keyboard::A)) player1.key["L"]=true;

if (Keyboard::isKeyPressed(Keyboard::D)) player1.key["R"]=true;

if (Keyboard::isKeyPressed(Keyboard::W)){ player1.key["Up"]=true;if(!player1.onLadder) jump.play();}

if (Keyboard::isKeyPressed(Keyboard::S)) player1.key["Down"]=true;

if (Keyboard::isKeyPressed(Keyboard::Escape))

{ enter.play();

ingame=0;

newgame=1;

text5.setString("Game");

text5.setColor(Color::White);

reset=1;

goto pro1;

}

}

if(ingame==0)

{

if(newgame==1)

{

text.setColor(Color::Green);

text8.setColor(Color::White);

text3.setColor(Color::White);

if (Keyboard::isKeyPressed(Keyboard::D))

{ change.play();

newgame=0;

reite=0;

esc=0;

reit=1;

ingame=0;

}

if (Keyboard::isKeyPressed(Keyboard::S))

{ change.play();

reite=0;

esc=1;

reit=0;

ingame=0;

}

}

if(reit==1)

{

text.setColor(Color::White);

text8.setColor(Color::Green);

text3.setColor(Color::White);

if (Keyboard::isKeyPressed(Keyboard::S))

{change.play();

reit=0;

reite=0;

esc=1;

newgame=0;

ingame=0;

}

if (Keyboard::isKeyPressed(Keyboard::A))

{ change.play();

reit=0;

reite=0;

esc=0;

ingame=0;

newgame=1;

}

if (Keyboard::isKeyPressed(Keyboard::E))

{enter.play();

reite=1;

}

}

if(esc)

{

newgame=0;

reit=0;

text8.setColor(Color::White);

text.setColor(Color::White);

text3.setColor(Color::Green);

if (Keyboard::isKeyPressed(Keyboard::W))

{change.play();

reite=0;

reit=0;

newgame=1;

esc=0;

}

}

}

for(it=entities.begin();it!=entities.end();)

{

Entity *b = *it;

b->update(time);

if (b->life==false) { it = entities.erase(it); delete b;}

else it++;

}

player1.update(time);

if(buf!=player1.Health)

{

buf=player1.Health;

hit.play();

}

if(player1.Health<=0)

{

text5.setString("Game over");

text5.setColor(Color::Red);

text5.setCharacterSize(50);

player1.Health=10;

ingame=0;

newgame=1;

reset=1;

buf=100;

goto pro1;

}

if(newgame)

{

text.setCharacterSize(32);

text8.setCharacterSize(24);

text3.setCharacterSize(24);

}

if(reit)

{

text.setCharacterSize(24);

text8.setCharacterSize(32);

text3.setCharacterSize(24);

}

if(esc)

{

text.setCharacterSize(24);

text8.setCharacterSize(24);

text3.setCharacterSize(32);

}

if(player1.Health>0&&ingame==1)

{

text5.setString("Game");

text5.setColor(Color::Green);

}

menuspr.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2, window.getView().getCenter().y - window.getView().getSize().y/2);

pictspr.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2, window.getView().getCenter().y - window.getView().getSize().y/2);

text.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 100-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 100);

text8.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 280-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 100);

text3.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 100-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 140);

text2.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 100-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 180);

text4.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 180-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 180);

text5.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 100-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 220);

text6.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 180-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 260);

text7.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 100-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 260);

text9.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 210-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 180);

text10.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 200-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 180);

text11.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 100-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 380);

text12.setPosition( window.getView().getCenter().x - window.getView().getSize().x/2 + 280-53, window.getView().getCenter().y - window.getView().getSize().y/2 + 140);

for(it=entities.begin();it!=entities.end();it++)

{

if ((*it)->Name=="Enemy")

{

Entity *enemy = *it;

if (enemy->Health<=0) continue;

if (player1.getRect().intersects( enemy->getRect() ))

if (player1.dy>0) { enemy->dx=0; player1.dy=-0.2; enemy->Health=0;}

else if (!player1.hit) { player1.Health-=5; player1.hit=true;

if (player1.dir) player1.x+=10; else player1.x-=10;}

for (std::list<Entity*>::iterator it2=entities.begin(); it2!=entities.end(); it2++)

{

Entity *bullet = *it2;

if (bullet->Name=="Bullet")

if ( bullet->Health>0)

if (bullet->getRect().intersects( enemy->getRect() ) )

{ bullet->Health=0; enemy->Health-=5;}

}

}

if ((*it)->Name=="MovingPlatform")

{

Entity *movPlat = *it;

if (player1.getRect().intersects( movPlat->getRect() ) )

if (player1.dy>0)

if (player1.y+player1.h<movPlat->y+movPlat->h)

{player1.y=movPlat->y - player1.h + 3; player1.x+=movPlat->dx*time; player1.dy=0; player1.STATE=PLAYER::stay;}

}

if ((*it)->Name=="Coin")

{

Entity *coin = *it;

if (player1.getRect().intersects( coin->getRect() ) )

{

if(coin->Health!=0)

res++;

coin->Health=0;

if(win==res)

{

text5.setString("Victory!");

text5.setColor(Color::Blue);

text5.setCharacterSize(50);

ingame=0;

newgame=1;

esc=0;

reit=0;

goto pro1;

}

}

}

/*рисуем*/

view.setCenter( player1.x,player1.y);

window.setView(view);

window.clear(Color(107,140,255));

}

if(ingame==0)

{

window.draw(menuspr);

window.draw(text);

window.draw(text2);

window.draw(text3);

window.draw(text4);

window.draw(text5);

window.draw(text8);

window.draw(text9);

window.draw(text10);

window.draw(text11);

if(reite)

window.draw(text12);

}

if(ingame)

{

window.draw(pictspr);

lvl.Draw(window);

for(it=entities.begin();it!=entities.end();it++)

(*it)->draw(window);

player1.draw(window);

window.draw(text2);

window.draw(text4);

window.draw(text5);

window.draw(text6);

window.draw(text7);

window.draw(text9);

window.draw(text10);

}

window.display();

}

return 0;

}

#ifndef LEVEL_H

#define LEVEL_H

#include <string>

#include <vector>

#include <map>

#include <SFML/Graphics.hpp>

#include <iostream>

#include "TinyXML/tinyxml.h"

struct Object

{

int GetPropertyInt(std::string name);

float GetPropertyFloat(std::string name);

std::string GetPropertyString(std::string name);

std::string name;

std::string type;

sf::Rect<float> rect;

std::map<std::string, std::string> properties;

sf::Sprite sprite;

};

struct Layer

{

int opacity;

std::vector<sf::Sprite> tiles;

};

class Level

{

public:

bool LoadFromFile(std::string filename);

Object GetObject(std::string name);

std::vector<Object> GetObjects(std::string name);

std::vector<Object> GetAllObjects();

void Draw(sf::RenderWindow &window);

sf::Vector2i GetTileSize();

private:

int width, height, tileWidth, tileHeight;

int firstTileID;

sf::Rect<float> drawingBounds;

sf::Texture tilesetImage;

std::vector<Object> objects;

std::vector<Layer> layers;

};

///////////////////////////////////////

int Object::GetPropertyInt(std::string name)

{

return atoi(properties[name].c_str());

}

float Object::GetPropertyFloat(std::string name)

{

return strtod(properties[name].c_str(), NULL);

}

std::string Object::GetPropertyString(std::string name)

{

return properties[name];

}

bool Level::LoadFromFile(std::string filename)

{

TiXmlDocument levelFile(filename.c_str());

// Загружаем XML-карту

if(!levelFile.LoadFile())

{

std::cout << "Loading level \"" << filename << "\" failed." << std::endl;

return false;

}

// Работаем с контейнером map

TiXmlElement *map;

map = levelFile.FirstChildElement("map");

// Пример карты: <map version="1.0" orientation="orthogonal"

// width="10" height="10" tilewidth="34" tileheight="34">

width = atoi(map->Attribute("width"));

height = atoi(map->Attribute("height"));

tileWidth = atoi(map->Attribute("tilewidth"));

tileHeight = atoi(map->Attribute("tileheight"));

// Берем описание тайлсета и идентификатор первого тайла

TiXmlElement *tilesetElement;

tilesetElement = map->FirstChildElement("tileset");

firstTileID = atoi(tilesetElement->Attribute("firstgid"));

// source - путь до картинки в контейнере image

TiXmlElement *image;

image = tilesetElement->FirstChildElement("image");

std::string imagepath = image->Attribute("source");

// Пытаемся загрузить тайлсет

sf::Image img;

if(!img.loadFromFile(imagepath))

{

std::cout << "Failed to load tile sheet." << std::endl;

return false;

}

img.createMaskFromColor(sf::Color(255, 255, 255));

tilesetImage.loadFromImage(img);

tilesetImage.setSmooth(false);

// Получаем количество столбцов и строк тайлсета

int columns = tilesetImage.getSize().x / tileWidth;

int rows = tilesetImage.getSize().y / tileHeight;

// Вектор из прямоугольников изображений (TextureRect)

std::vector<sf::Rect<int>> subRects;

for(int y = 0; y < rows; y++)

for(int x = 0; x < columns; x++)

{

sf::Rect<int> rect;

rect.top = y * tileHeight;

rect.height = tileHeight;

rect.left = x * tileWidth;

rect.width = tileWidth;

subRects.push_back(rect);

}

// Работа со слоями

TiXmlElement *layerElement;

layerElement = map->FirstChildElement("layer");

while(layerElement)

{

Layer layer;

// Если присутствует opacity, то задаем прозрачность слоя, иначе он полностью непрозрачен

if (layerElement->Attribute("opacity") != NULL)

{

float opacity = strtod(layerElement->Attribute("opacity"), NULL);

layer.opacity = 255 * opacity;

}

else

{

layer.opacity = 255;

}

// Контейнер <data>

TiXmlElement *layerDataElement;

layerDataElement = layerElement->FirstChildElement("data");

if(layerDataElement == NULL)

{

std::cout << "Bad map. No layer information found." << std::endl;

}

// Контейнер <tile> - описание тайлов каждого слоя

TiXmlElement *tileElement;

tileElement = layerDataElement->FirstChildElement("tile");

if(tileElement == NULL)

{

std::cout << "Bad map. No tile information found." << std::endl;

return false;

}

int x = 0;

int y = 0;

while(tileElement)

{

int tileGID = atoi(tileElement->Attribute("gid"));

int subRectToUse = tileGID - firstTileID;

// Устанавливаем TextureRect каждого тайла

if (subRectToUse >= 0)

{

sf::Sprite sprite;

sprite.setTexture(tilesetImage);

sprite.setTextureRect(subRects[subRectToUse]);

sprite.setPosition(x * tileWidth, y * tileHeight);

sprite.setColor(sf::Color(255, 255, 255, layer.opacity));

layer.tiles.push_back(sprite);

}

tileElement = tileElement->NextSiblingElement("tile");

x++;

if (x >= width)

{

x = 0;

y++;

if(y >= height)

y = 0;

}

}

layers.push_back(layer);

layerElement = layerElement->NextSiblingElement("layer");

}

// Работа с объектами

TiXmlElement *objectGroupElement;

// Если есть слои объектов

if (map->FirstChildElement("objectgroup") != NULL)

{

objectGroupElement = map->FirstChildElement("objectgroup");

while (objectGroupElement)

{

// Контейнер <object>

TiXmlElement *objectElement;

objectElement = objectGroupElement->FirstChildElement("object");

while(objectElement)

{

// Получаем все данные - тип, имя, позиция, etc

std::string objectType;

if (objectElement->Attribute("type") != NULL)

{

objectType = objectElement->Attribute("type");

}

std::string objectName;

if (objectElement->Attribute("name") != NULL)

{

objectName = objectElement->Attribute("name");

}

int x = atoi(objectElement->Attribute("x"));

int y = atoi(objectElement->Attribute("y"));

int width, height;

sf::Sprite sprite;

sprite.setTexture(tilesetImage);

sprite.setTextureRect(sf::Rect<int>(0,0,0,0));

sprite.setPosition(x, y);

if (objectElement->Attribute("width") != NULL)

{

width = atoi(objectElement->Attribute("width"));

height = atoi(objectElement->Attribute("height"));

}

else

{

width = subRects[atoi(objectElement->Attribute("gid")) - firstTileID].width;

height = subRects[atoi(objectElement->Attribute("gid")) - firstTileID].height;

sprite.setTextureRect(subRects[atoi(objectElement->Attribute("gid")) - firstTileID]);

}

// Экземпляр объекта

Object object;

object.name = objectName;

object.type = objectType;

object.sprite = sprite;

sf::Rect <float> objectRect;

objectRect.top = y;

objectRect.left = x;

objectRect.height = height;

objectRect.width = width;

object.rect = objectRect;

// "Переменные" объекта

TiXmlElement *properties;

properties = objectElement->FirstChildElement("properties");

if (properties != NULL)

{

TiXmlElement *prop;

prop = properties->FirstChildElement("property");

if (prop != NULL)

{

while(prop)

{

std::string propertyName = prop->Attribute("name");

std::string propertyValue = prop->Attribute("value");

object.properties[propertyName] = propertyValue;

prop = prop->NextSiblingElement("property");

}

}

}

objects.push_back(object);

objectElement = objectElement->NextSiblingElement("object");

}

objectGroupElement = objectGroupElement->NextSiblingElement("objectgroup");

}

}

else

{

std::cout << "No object layers found..." << std::endl;

}

return true;

}

Object Level::GetObject(std::string name)

{

// Только первый объект с заданным именем

for (int i = 0; i < objects.size(); i++)

if (objects[i].name == name)

return objects[i];

}

std::vector<Object> Level::GetObjects(std::string name)

{

// Все объекты с заданным именем

std::vector<Object> vec;

for(int i = 0; i < objects.size(); i++)

if(objects[i].name == name)

vec.push_back(objects[i]);

return vec;

}

std::vector<Object> Level::GetAllObjects()

{

return objects;

};

sf::Vector2i Level::GetTileSize()

{

return sf::Vector2i(tileWidth, tileHeight);

}

void Level::Draw(sf::RenderWindow &window)

{

// Рисуем все тайлы (объекты НЕ рисуем!)

for(int layer = 0; layer < layers.size(); layer++)

for(int tile = 0; tile < layers[layer].tiles.size(); tile++)

window.draw(layers[layer].tiles[tile]);

}

#endif

#ifndef ANIM_H

#define ANIM_H

#include "TinyXML/tinyxml.h"

#include <SFML/Graphics.hpp>

using namespace sf;

class Animation

{

public:

std::vector<IntRect> frames, frames_flip;

float currentFrame, speed;

bool loop, flip, isPlaying; // loop показвает зациклена ли анимация. Например анимация взрыва должна проиграться один раз и остановиться, loop=false

Sprite sprite;

Animation()

{

currentFrame = 0;

isPlaying=true;

flip=false;

}

void tick(float time)

{

if (!isPlaying) return;

currentFrame += speed * time;

if (currentFrame > frames.size()) { currentFrame -= frames.size();

if (!loop) {isPlaying=false; return;}

}

int i = currentFrame;

sprite.setTextureRect( frames[i] );

if (flip) sprite.setTextureRect( frames_flip[i] );

}

};

class AnimationManager

{

public:

String currentAnim;

std::map<String, Animation> animList;

AnimationManager()

{}

~AnimationManager()

{ animList.clear();

}

//создание анимаций вручную

void create(String name, Texture &texture, int x, int y, int w, int h, int count, float speed, int step=0, bool Loop=true)

{

Animation a;

a.speed = speed;

a.loop = Loop;

a.sprite.setTexture(texture);

a.sprite.setOrigin(0,h);

for (int i=0;i<count;i++)

{

a.frames.push_back( IntRect(x+i*step, y, w, h) );

a.frames_flip.push_back( IntRect(x+i*step+w, y, -w, h) );

}

animList[name] = a;

currentAnim = name;

}

//загрузка из файла XML

void loadFromXML(std::string fileName,Texture &t)

{

TiXmlDocument animFile(fileName.c_str());

animFile.LoadFile();

TiXmlElement *head;

head = animFile.FirstChildElement("sprites");

TiXmlElement *animElement;

animElement = head->FirstChildElement("animation");

while(animElement)

{

Animation anim;

currentAnim = animElement->Attribute("title");

int delay = atoi(animElement->Attribute("delay"));

anim.speed = 1.0/delay; anim.sprite.setTexture(t);

TiXmlElement *cut;

cut = animElement->FirstChildElement("cut");

while (cut)

{

int x = atoi(cut->Attribute("x"));

int y = atoi(cut->Attribute("y"));

int w = atoi(cut->Attribute("w"));

int h = atoi(cut->Attribute("h"));

anim.frames.push_back( IntRect(x,y,w,h) );

anim.frames_flip.push_back( IntRect(x+w,y,-w,h) );

cut = cut->NextSiblingElement("cut");

}

anim.sprite.setOrigin(0,anim.frames[0].height);

animList[currentAnim] = anim;

animElement = animElement->NextSiblingElement("animation");

}

}

void set(String name)

{

currentAnim = name;

animList[currentAnim].flip=0;

}

void draw(RenderWindow &window,int x=0, int y=0)

{

animList[currentAnim].sprite.setPosition(x,y);

window.draw( animList[currentAnim].sprite );

}

void flip(bool b=1) {animList[currentAnim].flip = b;}

void tick(float time) {animList[currentAnim].tick(time);}

void pause() {animList[currentAnim].isPlaying=false;}

void play() {animList[currentAnim].isPlaying=true;}

void play(String name) {animList[name].isPlaying=true;}

bool isPlaying() {return animList[currentAnim].isPlaying;}

float getH() {return animList[currentAnim].frames[0].height;}

float getW() {return animList[currentAnim].frames[0].width;}

};

#endif ANIM_H