Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> прорисовка двумерного массива 
:(
    Опции темы
lenarano
Дата 3.11.2015, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



Да, точно.
Все запустилось, но ничего не отображается. Все данные хранятся тут std::list<Point>();
Я решила уйти от изображения 'G' на карте, а передать реальные координаты игрока.
В main, где есть описание взаимодействия со врагом взяла координаты игрока
(*it)->getPlayerCoord(pacman.x,pacman.y);
Она у меня описана в базовом классе
void Entity::getPlayerCoord(float X,float Y)
    {
        px=X;
        py=Y;
    }

 получила рх и ру игрока и уже в функции void update(float time) врага
вызываю свой алгоритм поиска find_path(x, y, px, py);
И соответственно переделала саму фунцию
Код

std::list<Point> find_path(int start_x, int start_y, int pacman_x,int pacman_y) {
        if ( start_x < 0 || start_x > m_map->WIDTH_MAP - 1 || start_y < 0 || start_y >  m_map->HEIGHT_MAP - 1 )
            return std::list<Point>(); // Empty list
        flag tempMap[m_map->HEIGHT_MAP][m_map->WIDTH_MAP];
        for(int y =0; y < m_map->HEIGHT_MAP; y++)
            for(int x =0; x < m_map->WIDTH_MAP; x++) {
                flag f;
                switch (m_map->TileMap[y][x]) {
                case ' ': f = free; break;
                case 'O': f = wall; break;
            //    case 'G': f = endpoint;
                }
                tempMap[y][x] = f;
            }
            tempMap[start_y][start_x] = startpoint;
            tempMap[pacman_y][pacman_x] = endpoint;
            std::list<Point> path;
            return find_path(x, y, tempMap, path); // Вызываем рекурсивную функцию
    }




Т.е. теперь у меня в лист передалась информация и о положении моего реального героя и врага. Правильно?

Добавлено через 14 минут и 56 секунд
Теперь find_path(x, y, px, py); передает реальные координаты врага и героя и находит путь, но я его не вижу.
PM MAIL   Вверх
lenarano
Дата 3.11.2015, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



Как сделать, чтобы враг начал двигаться? 
Теперь нужно создать еще одну функцию,в которую мне нужно будет передать мой лист, где расписан путь.в которой координаты моего врага будут меняться, т.е. смотрим вокруг и если не стенка и путь свободен перешли туда и делать это с определенной скоростью. Предположем эту скорость я смогу отрегулировать в самой функции движения и менять ее в зависимости от необходимости. Но я так и не могу понять как реализовать передвижение врага.
Я нашла в интернете вот это
1.Этaп построения мaршрутa перемещения. Присвaивaем переменным Х и Y знaчения координaт стaртовой позиции.
Это готово
В окрестности позиции R(Х,Y) ищем элемент с нaименьшим знaчением (т.е.для этого просмaтривaем R(Х+1,Y), R(Х-1,Y), R(Х,Y+1), R(Х,Y-1). Координaты этого элементa зaносим в переменные X1 и Y1.
Совершaем перемещение объектa (кто тaм у вaс будет - робот, aквaнaвт, Винни-Пух) по игровому полю из позиции [X,Y] в позицию [X1,Y1].
Если R(X1,Y1)=0,то переходим к пункту 15.
Выполняем присвaивaние X:=X1,Y:=Y1. Переходим к пункту 11.

По поводу отрисовки , то она фактически и есть в функции движения, когда мы меняем х и у(т.е. местоположение на карте), 
то уже все родные функции SFML перемещают игрока или врага. Поэтому мне кажется тут нужно работать именно с x  и у.
PM MAIL   Вверх
math64
Дата 3.11.2015, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Слои библиотека поддерживает? Если да, соединить точки из list<Point> линией.
Если нет, заменить на карте в точках из списка на свой символ, запомнив старый а занем вернуть назад:
Код

void ShowPath(const std::list<Point>& path, char*& saved)
{
  saved = new char[path.size()];
  for(int i = 0; i < path.size; i++) {
   int x = path[i].x, y = path[i].y;
   saved[i] =m_map->TileMap[y][x];
   m_map->TileMap[y][x] = '+';
 }
}
void ClearPath(const std::list<Point>& path, char* saved)
{
  for(int i = 0; i < path.size; i++) {
   int x = path[i].x, y = path[i].y;
   m_map->TileMap[y][x] = saved[i];
 }
 delete saved;
}


Добавлено через 11 минут и 59 секунд
Цитата(lenarano @  3.11.2015,  14:37 Найти цитируемый пост)
Как сделать, чтобы враг начал двигаться?

Найденный путь запоминается в поле класса Enemy.
Проверять на свободность клеток не обязательно - это было сделано при поиске пути.
Враг движется от path[0] до path[1] при float t измемающемся от 0 до 1
Код

x = (float)path[0].x * (1-t) + (float)path[1].x * t;
y = (float)path[0].y * (1-t) + (float)path[1].y * t;

Когда t становится 1, из path удаляется первый элемент (глупый враг) или path пересчитывается (умный враг). Пересчет происходит также, когда в path оствается меньше 2 точек.
PM   Вверх
lenarano
Дата 3.11.2015, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



int x = path[i].x, y = path[i].y;//вот тут ругается [i
появились ошибки:
отсутствует оператор[], соответствующий этим операндам.


Я, поняла эти функции так.
Вставила их в мой класс врага и с помощью этих функций у меня должна отобразиться дорожка
Код

void ShowPath(const std::list<Point>& path, char*& saved)//& работаем с адресом и соответственно изменяем переменные
    {
        saved = new char[path.size()];//создаем массив символов разменостью =лист;saved указывает место в памяти
        for(int i = 0; i < path.size; i++) {
            int x = path[i].x, y = path[i].y;//заносим в х и у значения координат
            saved[i] =m_map->TileMap[y][x];//наши нужные координаты, которые потом восстановим -заносим по нашему адресу
            m_map->TileMap[y][x] = '+';//вместо них рисуем символ
        }
    }

void ClearPath(const std::list<Point>& path, char* saved)
    {
        for(int i = 0; i < path.size; i++) {
            int x = path[i].x, y = path[i].y;
            m_map->TileMap[y][x] = saved[i];//заносим сохраненные значения
        }
        delete saved;//удаляем, потому что не нужны
    }


Это сообщение отредактировал(а) lenarano - 3.11.2015, 15:34
PM MAIL   Вверх
math64
Дата 3.11.2015, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Ошибся. У std::list нет operator[]. Можно заменить на std::vector или
Код

i = 0;
for (std::list <int>::const_iterator I = my_list.begin (); I != my_list.end (); ++I, ++i) {
  int x = (*I).x, y = (*I).y;
  ...
}

или написать свой класс-контейнер.
И да, list::size() лучше не пользоваться - он слишком медленный.
Соответственно, при анамации врага, нужно забрать два первых элемента из  списка:
Код

point0 = path.front(); path.pop_front();
point1 = path.front(); path.pop_front();

PM   Вверх
lenarano
Дата 3.11.2015, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



заменила везде лист на вектор.
Код

void ShowPath(const std::vector<Point>& path, char*& saved)
    {
        saved = new char[path.size()];
        for(int i = 0; i < path.size(); i++) {
            int x = path[i].x, y = path[i].y;
            saved[i] =m_map->TileMap[y][x];
            m_map->TileMap[y][x] = '+';
        }
    }

 На этом этапе все запускается.

Код

И да, list::size() лучше не пользоваться - он слишком медленный.


Медленный потому что разбросаны элементы по памяти. Но при векторе все же расположено блоками-значит можно использовать. Правильно?


Это сообщение отредактировал(а) lenarano - 3.11.2015, 20:14
PM MAIL   Вверх
lenarano
Дата 3.11.2015, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



 smile 
Код

void ShowPath(const std::vector<Point>& path, char*& saved);
void ClearPath(const std::vector<Point>& path, char* saved);
  


Вот мы их расписали. Теперь их нужно прописать где-то в коде. Мы их прописываем в нашем коде после функции find_path(x, y, px, py)?
Чтобы дорожки прорисовывались. Тут я не понимаю. Нам нужно добавить поля класса  char* Saved и std::vector<Point> Path?
Правильно? И как параметры туда передавать? 
Код

Path=find_path(x, y, px, py);
ShowPath(Path, Saved);
ClearPath(Path, Saved);

Вызвали один раз find_path(x, y, px, py); а уже потом из этой функции запускается вторая return find_path(x, y, tempMap, path);, которая возвращает 
std::vector<Point>(); 
 Я правда стараюсь)))
Реализовала так как и говорила вверху. Все запустилось, но дорожки нет((( Когда делаю отладку, то вижу, что Path=find_path(x, y, px, py); Path=размер 0;
 Что не так? smile 



Это сообщение отредактировал(а) lenarano - 3.11.2015, 21:32
PM MAIL   Вверх
lenarano
Дата 3.11.2015, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



math64, Разжуйте мне, пожалуйста. Можно сразу функцией, а я ее закоментирую, как я ее понимаю. Мне так проще. Как раньше показывали. 
Код

Враг движется от path[0] до path[1] при float t изменяющемся от 0 до 1

x = (float)path[0].x * (1-t) + (float)path[1].x * t;
y = (float)path[0].y * (1-t) + (float)path[1].y * t;

Когда t становится 1, из path удаляется первый элемент (глупый враг) или path пересчитывается (умный враг). Пересчет происходит также, когда в path оствается меньше 2 точек. 


Вообще не представляю, как все это запустить. Очень вас прошу покажите мне, что куда вставить у меня в коде, чтобы все заработало. Очень надеюсь на вашу помощь
math64. Я саму игру по урокам с интернета быстрее написала, а на этой реализации споткнулась(((

Код

#ifndef ENEMY_H
#define ENEMY_H

#include "Entity.h"
#include <vector>




class Enemy:public Entity{
private:
    Map* m_map;
public:
    float CurrentFrame;
    struct Point { int x; int y;};
    char* Saved;//?
    std::vector<Point> Path;//?
    int zq,timer;
    enum flag {
        free = 0, // свободно
        wall = 1, // стенка
        gold = 2, // золото
        enemy = 4, // враг
        startpoint = 8, // начало пути
        endpoint = 16, // конец пути
        inpath = 32, // в пробном пути
        noway = 64, // проверено, что ведет в тупик
    };
    Enemy (Map* map,sf::Image &image,sf::String Name,float X, float Y, float W, float H): Entity(image,Name,X,Y,W,H){
        m_map=map;
        state=down;CurrentFrame=0;
        zq=1;timer=0;
        if(name=="EasyEnemy"){
            sprite.setTextureRect(sf::IntRect(0,0,w,h));
        }

    }

    void checkCollisionWithMap()//ф ция проверки столкновений с картой
    {
        for (int i = y / 32; i < (y + h) / 32; i++)
            for (int j = x / 32; j<(x + w) / 32; j++)
            {
                if (m_map->TileMap[i][j] == '0')
                {
                    if (dy>0){y = i * 32 - h;}
                    if (dy<0){y = i * 32 + 32;}
                    if (dx>0){x = j * 32 - w;}
                    if (dx < 0){x = j * 32 + 32;}
                }
            }
    }


    void update(float time)
    {
        if (name == "EasyEnemy"){//для персонажа с таким именем логика будет такой
            timer+=time;
            if (timer+1000>1000) {zq=rand()%3;}
            if (timer>500) {if (zq==0)  {if (x>px) {speed=0.1,state=left; timer=0;} {if (y>py) {speed=0.1,state=up; timer=0;} }}}
            if (timer>500) {if (zq==1)  {if (x<px) {speed=0.1,state=right; timer=0;} {if (y<py) {speed=0.1,state=down; timer=0;} }}}
            switch(state)
            {
            case right: dx=speed; dy=0;  break;
            case left: dx=-speed; dy=0;  break;
            case down: dx=0; dy=speed; break;
            case up: dx=0; dy=-speed;   break;
            case stay:break;            
            }

            x += dx*time;
            y += dy*time;
            checkCollisionWithMap();
            find_path(x, y, px, py);
            find_path( x, y, m_map->TileMap[Map::HEIGHT_MAP][Map::WIDTH_MAP], Path);
            ShowPath(Path, Saved);
            ClearPath(Path, Saved);

            sprite.setPosition(x + w / 2, y + h / 2); //задаем позицию спрайта в место его центра
            //////////анимация
            CurrentFrame+=0.005*time;
            if (CurrentFrame>3) CurrentFrame-=3;
            if (dx > 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),64,32,32));
            if (dx < 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),32,32,32));
            if (dy > 0) sprite.setTextureRect(sf::IntRect(32*int(CurrentFrame),0,32,32));
            if (dy < 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),97,32,32));
        }
    }


    std::vector<Point> find_path(int start_x, int start_y, int pacman_x,int pacman_y) {
        if ( start_x < 0 || start_x > m_map->WIDTH_MAP - 1 || start_y < 0 || start_y >  m_map->HEIGHT_MAP - 1 )
            return std::vector<Point>(); // Empty list
        flag tempMap[m_map->HEIGHT_MAP][m_map->WIDTH_MAP];
        for(int y =0; y < m_map->HEIGHT_MAP; y++)
            for(int x =0; x < m_map->WIDTH_MAP; x++) {
                flag f;
                switch (m_map->TileMap[y][x]) {
                case ' ': f = free; break;
                case 'O': f = wall; break;
                    //    case 'G': f = endpoint;
                }
                tempMap[y][x] = f;
            }
            tempMap[start_y][start_x] = startpoint;
            tempMap[pacman_y][pacman_x] = endpoint;
            std::vector<Point> path;
            return find_path(x, y, tempMap, path); // Вызываем рекурсивную функцию
            
    }

    std::vector<Point> find_path(int x, int y,flag tempMap[Map::HEIGHT_MAP][Map::WIDTH_MAP],std::vector<Point> path) {
        if ( x < 0 || x > m_map->WIDTH_MAP - 1 || y < 0 || y > m_map->HEIGHT_MAP - 1 )
            return std::vector<Point>(); // Empty list
        Point point = { x, y };
        path.push_back(point);
        // Если x,y-это цель, возвратите True.
        if ( (tempMap[y][x] & endpoint) != 0) return path;
        // Если x,y не открыть, вернуть false.
        if ( (tempMap[y][x] & wall) != 0)
            return std::vector<Point>();
        // Мы здесь уже были
        if ( (tempMap[y][x] & (inpath|noway)) != 0)
            return std::vector<Point>();
        tempMap[y][x] = inpath; // + часть решения, пути.
        // If find_path North of x,y is true, return true.
        std::vector<Point> ret_path;
        if ( !(ret_path = find_path(x, y - 1, tempMap, path)).empty() ) return ret_path;
        if ( !(ret_path = find_path(x + 1, y, tempMap, path)).empty() ) return ret_path;
        if ( !(ret_path = find_path(x, y + 1, tempMap, path)).empty() ) return ret_path;
        if ( !(ret_path = find_path(x - 1, y, tempMap, path)).empty() ) return ret_path;
        // Снять х,Y как часть решения, пути.
        tempMap[y][x] = (flag)(tempMap[y][x]&~inpath);
        tempMap[y][x] = noway;
        return std::vector<Point>();
    
    }

    void ShowPath(const std::vector<Point>& path, char*& saved)
    {
        saved = new char[path.size()];
        for(int i = 0; i < path.size(); i++) {
            int x = path[i].x, y = path[i].y;
            saved[i] =m_map->TileMap[y][x];
            m_map->TileMap[y][x] = '+';
        }
    }
    void ClearPath(const std::vector<Point>& path, char* saved)
    {
        for(int i = 0; i < path.size(); i++) {
            int x = path[i].x, y = path[i].y;
            m_map->TileMap[y][x] = saved[i];
        }
        delete saved;
    }



};

#endif ENTITY_H


Это сообщение отредактировал(а) lenarano - 3.11.2015, 21:07
PM MAIL   Вверх
math64
Дата 5.11.2015, 08:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72




Цитата(lenarano @  3.11.2015,  15:53 Найти цитируемый пост)
Медленный потому что разбросаны элементы по памяти. Но при векторе все же расположено блоками-значит можно использовать. Правильно?


Элементы std::vector хранятся в виде массива + его длина. Легко получить доступ к нужному элементу, узнать размер, легко добавить элемент в конец (если зареервировать массив нужного размера) и удалять из конца. Но трудно добавлять и удалять из середины.

Элементы std::list хранятся в виде списка. Лекго добавить и удалить  в начало и конец, вставить и удалить в середине, если найден нужный элемент,
но сам поиск элемента в середине - долгая операция.
Размер списка не хранится отдельно, поэтому size() каждый раз считает число элементов - но это особенность реализации.

У вас есть Enemy::update(float time);
В ней нужно делать примерно так:
Код

timer += time;
if (timer >= 1) {
   if (DEBUG && Save != nullptr) {
     ClearPath(Path, Save);
     Save = nullptr;
   }
   timer = 0;
   Path.pop_front();
}
if (Path.size() < 2)
{
   Path = find_path();
   // После этого Path[0] = текущее положение, Path[1] - следующее положение.
   if (DEBUG)
     ShowPath(Path,Save);
}
float x = (float)Path[0].x * (1-timer) + (float)Path[1].x * timer;
float y = (float)Path[0].y * (1-timer) + (float)Path[1].y * timer;
// Если враг крутится, развернуть его в направлении от Path[0] до Path[1]
// отобразить спрайт врага в позиции x, y

В заголовке определить const bool DEBUG = true; или false; (или #define DEBUG true) в зависимости от того, нужна отладка или нет.
PM   Вверх
lenarano
Дата 5.11.2015, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



При компиляции ошибок не выдает, но при запуске появляется информация
vector erase iterator  outside range //вектор стереть итератор вне диапазона
Path.pop_front() я заменила на Path.erase(Path.begin()) , т.к. в векторе не было такой функции
При отладке Path = find_path(x,y,px,py);   Path по-прежнему указывает,что ровна 0
Saved при наведении пишет ошибку при чтении символов строки
Ошибка при отладке происходит, когда доходит до этой строки:
Path.erase(Path.begin());//Удаляет элемент в начале списка.

Вообще, я поняла, что изначально должен прорабатываться алгоритм поиска пути, потом показываться и потом очищаться путь,
 а получается, что сразу же прорабатывается вот этот кусочек кода
Код

timer += time;
        if (timer >= 1) {
            if (DEBUG && Saved != nullptr)//отладка и указатель на что-то указывает
            {
                ClearPath( Path, Saved);//возращаем карту как было
                Saved = nullptr;//указатель пустой
            }
            timer = 0;
      //  Path.pop_front();
        Path.erase(Path.begin());//Удаляет элемент в начале списка.
        }


Это происходит, т.к. timer сразу больше 1(значение больше 1000 при отладке)

Еще хотела спросить-нужно ли иницилизировать эти значения вначале в конструкторе, или их достаточно определить? 
Код

char* Saved;//?
std::vector<Point> Path;//?


Еще ругается вот тут, работает в режиме, когда отладка=true;
Код

void ClearPath(const std::vector<Point>& path, char* saved)
{
    for(int i = 0; i < path.size(); i++) {
        int x = path[i].x, y = path[i].y;
        m_map->TileMap[y][x] = saved[i];
    }
    delete saved;//вот тут!!!!!!!!
}



Помогите. smile 




Это сообщение отредактировал(а) lenarano - 6.11.2015, 21:28
PM MAIL   Вверх
math64
Дата 6.11.2015, 08:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



delete[] Saved;
Saved нужно инициализировать, Path не обязательно (вызывается конструктор по умолчаниию).
Приводимый мной код примерный - в нем могут быть ошибки.
Да, Path должен быть вычислен до того, как враг начинает двигаться. После вычисления нужно проверить, что в Path хотя бы два элемента и если он пустой оставлять врага неподвижным или он будет двигаться на случайную соседнюю свободную клетку.
И find_path скорее всего, нужно будет оптимизировать, чтобы он выводил более короткий путь - сейчас враг предпочтёт начать двигаться на север, даже если цель на юге.
PM   Вверх
lenarano
Дата 6.11.2015, 21:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



Внесла правки, на который указывали. пробовала отладку и нашла пару вроде ошибок

 
Код

std::vector<Point> find_path(int start_x, int start_y, int pacman_x,int pacman_y)
if ( start_x < 0 || start_y < 0 )//значения х и у может быть больше размера карты


Код

return find_path(start_x, start_y, tempMap, path); // Вызываем рекурсивную функцию

Раньше было так find_path(x, y, tempMap, path); и получалось, что мы не то нашли

Правильно?

При отладке вижу, что застреваем в std::vector<Point> find_path(int start_x, int start_y, int pacman_x,int pacman_y)
Вроде проходимся по алгоритму, а потом застреваем тут
    tempMap[start_y][start_x] = startpoint;
Ошибка :необработанное исключение, нарушение прав доступа при записи

Может посмотрите еще, какую ошибку я не замечаю


Слушаете, а может быть ситуация тупо в значениях которые мы передаем в нашу функцию
start_x у меня по координатам =410, а мы его пробуем впихнуть в карту   tempMap[start_y][start_x] = startpoint;
И возникает вопрос, если это игровые координаты то как мне перейти к ним?


Код

#ifndef ENEMY_H
#define ENEMY_H

#define DEBUG true

#include "Entity.h"
#include <vector>




class Enemy:public Entity{
private:
    Map* m_map;
public:
    float CurrentFrame;
    struct Point { int x; int y;};
    char* Saved;
    std::vector<Point> Path;
    int timer;
    enum flag {
        free = 0, // свободно
        wall = 1, // стенка
        gold = 2, // золото
        enemy = 4, // враг
        startpoint = 8, // начало пути
        endpoint = 16, // конец пути
        inpath = 32, // в пробном пути
        noway = 64, // проверено, что ведет в тупик
    };
    Enemy (Map* map,sf::Image &image,sf::String Name,float X, float Y, float W, float H): Entity(image,Name,X,Y,W,H){
        m_map=map;
        state=down;CurrentFrame=0;
        timer=0;
        Saved=0;
        if(name=="EasyEnemy"){
            sprite.setTextureRect(sf::IntRect(0,0,w,h));
        }

    }

    void checkCollisionWithMap()//ф ция проверки столкновений с картой
    {
        for (int i = y / 32; i < (y + h) / 32; i++)
            for (int j = x / 32; j<(x + w) / 32; j++)
            {
                if (m_map->TileMap[i][j] == '0')
                {
                    if (dy>0){y = i * 32 - h;}
                    if (dy<0){y = i * 32 + 32;}
                    if (dx>0){x = j * 32 - w;}
                    if (dx < 0){x = j * 32 + 32;}
                }
            }
    }


    void update(float time)
    {
    timer += time/10000;//сначала значение меньше 1
        if (timer >= 1) {
            if (DEBUG && Saved != nullptr)//отладка и указатель на что-то указывает
            {
                ClearPath( Path, Saved);//возращаем карту как было
                Saved = nullptr;//указатель пустой
            }
            timer = 0;
      
        Path.erase(Path.begin());//Удаляет элемент в начале списка.
        }
        if (Path.size() < 2)//если меньше 2
        {
            Path = find_path(x,y,px,py);//получем вектор
            // После этого Path[0] = текущее положение, Path[1] - следующее положение.
            if (DEBUG)//отладка
                ShowPath(Path,Saved);//покажем на карте путь
        }
        float x = (float)Path[0].x * (1-timer) + (float)Path[1].x * timer;
        float y = (float)Path[0].y * (1-timer) + (float)Path[1].y * timer;
        // Если враг крутится, развернуть его в направлении от Path[0] до Path[1]
        // отобразить спрайт врага в позиции x, y
                
        switch(state)
        {
        case right: dx=speed; dy=0;  break;
        case left: dx=-speed; dy=0;  break;
        case down: dx=0; dy=speed; break;
        case up: dx=0; dy=-speed;   break;
        case stay:break;            
        }

        x += dx*time;
        y += dy*time;
        checkCollisionWithMap();
        sprite.setPosition(x + w / 2, y + h / 2); //задаем позицию спрайта в место его центра
        //////////анимация
        CurrentFrame+=0.005*time;
        if (CurrentFrame>3) CurrentFrame-=3;
        if (dx > 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),64,32,32));
        if (dx < 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),32,32,32));
        if (dy > 0) sprite.setTextureRect(sf::IntRect(32*int(CurrentFrame),0,32,32));
        if (dy < 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),97,32,32));
    }



std::vector<Point> find_path(int start_x, int start_y, int pacman_x,int pacman_y) {
    
    if ( start_x < 0 || start_y < 0 )
    return std::vector<Point>(); // Empty list
    flag tempMap[m_map->HEIGHT_MAP][m_map->WIDTH_MAP];
    for(int y =0; y < m_map->HEIGHT_MAP; y++)
        for(int x =0; x < m_map->WIDTH_MAP; x++) {
            flag f;
            switch (m_map->TileMap[y][x]) {
            case ' ': f = free; break;
            case '0': f = wall; break;
        //    case 'G': f = endpoint;
       //   case 'S': f = startpoint;
            }
            tempMap[y][x] = f;
        }
    //    tempMap[start_y][start_x] = startpoint;
    //    tempMap[pacman_y][pacman_x] = endpoint;
        std::vector<Point> path;
        return find_path(start_x, start_y, tempMap, path); // Вызываем рекурсивную функцию

}

std::vector<Point> find_path(int x, int y,flag tempMap[Map::HEIGHT_MAP][Map::WIDTH_MAP],std::vector<Point> path) {
    
    if ( x < 0 ||  y < 0  )
        return std::vector<Point>(); // Empty list
    Point point = { x, y };
    path.push_back(point);
    // Если x,y-это цель, возвратите True.
    if ( (tempMap[y][x] & endpoint) != 0) return path;
    // Если x,y не открыть, вернуть false.
    if ( (tempMap[y][x] & wall) != 0)
        return std::vector<Point>();
    // Мы здесь уже были
    if ( (tempMap[y][x] & (inpath|noway)) != 0)
        return std::vector<Point>();
    tempMap[y][x] = inpath; // + часть решения, пути.
    // If find_path North of x,y is true, return true.
    std::vector<Point> ret_path;
    if ( !(ret_path = find_path(x, y - 1, tempMap, path)).empty() ) return ret_path;
    if ( !(ret_path = find_path(x + 1, y, tempMap, path)).empty() ) return ret_path;
    if ( !(ret_path = find_path(x, y + 1, tempMap, path)).empty() ) return ret_path;
    if ( !(ret_path = find_path(x - 1, y, tempMap, path)).empty() ) return ret_path;
    // Снять х,Y как часть решения, пути.
    tempMap[y][x] = (flag)(tempMap[y][x]&~inpath);
    tempMap[y][x] = noway;
    return std::vector<Point>();

}

void ShowPath(const std::vector<Point>& path, char*& saved)
{
    saved = new char[path.size()];
    for(int i = 0; i < path.size(); i++) {
        int x = path[i].x, y = path[i].y;
        saved[i] =m_map->TileMap[y][x];
        m_map->TileMap[y][x] = '+';
    }
}
void ClearPath(const std::vector<Point>& path, char* saved)
{
    for(int i = 0; i < path.size(); i++) {
        int x = path[i].x, y = path[i].y;
        m_map->TileMap[y][x] = saved[i];
    }
    delete []saved;
}



};




#endif ENTITY_H


Это сообщение отредактировал(а) lenarano - 6.11.2015, 22:26
PM MAIL   Вверх
math64
Дата 9.11.2015, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



По идее нужно добавить деструктор и сделать там delete[] Save или ClearPath() - на случай если враг будет удалён до того, как будет вызван ClearPath().
Также, вообще-то враг не должен выходить за пределы карты. Если от вылез - лучше поправить координаты 
Код

if (x < 0) x = 0;
if (x >= WIDTH_MAP) x = WIDTH_MAP -1;

Вероятно в Entity есть поля float x; float y;
Этот код скрывает их: 
Код

float x = (float)Path[0].x * (1-timer) + (float)Path[1].x * timer;
float y = (float)Path[0].y * (1-timer) + (float)Path[1].y * timer;

Это по видимому не нужно (уже учтено в коде выше):
Код

x += dx*time;
y += dy*time;



PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0988 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.