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

Поиск:

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


Шустрый
*


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

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



На данный момент нужна помощь в том, что я не могу вывести levelsMap в поле класса, возникают ошибки. Если кто то покажет, как это будет-буду рада, может опять что-то упускаю. Если оставить как есть, то тогда естественно моя функция прорисовки void Map::display_maze( int level) его не видит. Подскажите пути исправления


Код

#ifndef MAP_H
#define MAP_H
#include <SFML\Graphics.hpp>
class Map{
private:
int m_level;
 
public: 
   enum { HEIGHT_MAP=25, WIDTH_MAP=28 };
   sf::String TileMap[HEIGHT_MAP];
 
 Map();
 
 int getLevel();
 
 void setLevel(int level);
 
 void display_maze( int level);
};
 
 
 
#include "map.h"
 
#include <iostream>
 
 
 
Map::Map()
{
    setLevel(0);
    
}
 
int Map:: getLevel() { return m_level; }
 
void Map:: setLevel(int level)
{
    static const char* levelsMap[][HEIGHT_MAP] = {
        { 
                "0000000000000000000000000000",/* Инициализация 0-го уровня */
                "0   S                      0",
                "0                          0",
                "0  0 s0   0      0   0s 0 G0",
                "0  0000   0mmmmmm0   0000  0",
                "0  0mm0   00000000   0mm0  0",
                "0                          0",
                "0                          0",
                "0  0mm0   000  000   0mm0  0",
                "0  0000   0      0   0000  0",
                "0  0mm0   0      0   0mm0  0",
                "t         000  000         T",
                "t                          T",
                "t                          T",
                "0  0mm0   00000000   0mm0  0",
                "0  0000              0000  0",
                "0  0mm0              0mm0  0",
                "0         00000000         0",
                "0                          0",
                "0  0mm0              0mm0  0",
                "0  0000   00000000   0000  0",
                "0  0 s0              0s 0  0",
                "0                          0",
                "0                          0",
                "0000000000000000000000000000", },
            {"0000000000000000000000000000", /* Инициализация 1-го уровня */ 
            "0                          0",
            "0                          0",
            "0  0                    0  0",
            "0  0000              0000  0",
            "0  0      000  000      0  0",
            "0         0      0         0",
            "0         0      0         0",
            "0  0mm    000  000    mm0  0",
            "0  0000              0000  0",
            "0  0                    0  0",
            "t         00000000         T",
            "t           m00m           T",
            "t           m00m           T",
            "0  0      00000000      0  0",
            "0  0000              0000  0",
            "0  0                    0  0",
            "0                          0",
            "0      0000      0000      0",
            "0  0      0s    s0      0  0",
            "0  0  0   00000000   0  0  0",
            "0  0  0   0mmmmmm0   0  0  0",
            "0                          0",
            "0                          0",
            "0000000000000000000000000000", },
            { /* Инициализация 2-го уровня */ },
    };
    int levelsCount = sizeof(levelsMap) / sizeof(levelsMap[0]);
    if (level < 0 || level >= levelsCount)
        level = 0;
    m_level = level;
    for(int i=0; i < HEIGHT_MAP; i++)
    {TileMap[i] = levelsMap[level][i];
    std::cout<<levelsMap[level][i];
    printf("\n");
    }
}
 
 
void Map::display_maze( int level)
{
    int i;
    printf("MAZE:\n");
    for(int i=0; i < Map::HEIGHT_MAP; i++)
    {TileMap[i] = levelsMap[level][i];
    std::cout<<levelsMap[level][i];
    printf("\n");
    }
 
    return;
}

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


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

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



Не понял, что Вы хотите, и что за ошибки возникают. Может, так:
Цитата(lenarano @  1.11.2015,  12:07 Найти цитируемый пост)
void Map::display_maze( int level)
{
    std::cout << "MAZE:" << std::endl;
    for( int i=0; i < Map::HEIGHT_MAP; i++)
    {
       TileMap[i] = levelsMap[level][i];
       std::cout << TileMap[i] << std::endl;
    }
}




--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 1.11.2015, 17:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(lenarano @  1.11.2015,  12:07 Найти цитируемый пост)
   static const char* levelsMap[][HEIGHT_MAP] = {
это нужно вынести из функции, иначе не видно снаружи.
в классе написать декларацию:
Код

static const char* levelsMap[][HEIGHT_MAP];

а где-то в спп-шнике определение:
Код

const char* Map::levelsMap[][HEIGHT_MAP] = {
    { 
            "0000000000000000000000000000",/* Инициализация 0-го уровня */
            "0   S                      0",
            "0                          0",
            ...

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


Шустрый
*


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

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



Спасибо всем, проблема была в том, что я пробовала иницилизировать его в конструкторе в срр файле, хотя до этого объявила его в заголовочном. Почему нельзя было?
Хотела еще спросить. Я эту прорисовку хотела использовать для того, чтобы видеть мой алгоритм кратчайшего пути. Т.е. по идее я должна была вызвать прорисовку карты,затем преобразование карты, и затем ту же прорисовку, но на ней должны были отобразиться изменения- + там где есть путь.
Сама прорисовка рабочая,т.е когда я запускаю игру с одной функцией преобразования, то мои тайлики выстраивают путь и я его вижу, но когда я делаю так:
Код

map->display_maze(0);
            
            if (map-> find_path(11, 15) == TRUE )
                printf("Success!\n");
        else
                printf("Failed\n");
             
    map->display_maze(0);

У меня в моей консольке видно, что массив не преобразуется и карта пути тайликами не прорисовывается. Я подумала,что у нас значения переменной константное,ничего не помогло.
 static  char* levelsMap[][HEIGHT_MAP];
Почему так?
PM MAIL   Вверх
lenarano
Дата 2.11.2015, 09:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



В вложениях показала как отрисовывается путь, когда работает только алгоритм поиска пути и когда сначала рисую массив, потом прорабатываю алгоритм и опять рисую ничего не вижу. Путь на массиве должен быть выложен "+",  а получается, что и не прорисовывается не в массиве и не на карте.

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  Безымянный.png 193,92 Kb
PM MAIL   Вверх
lenarano
Дата 2.11.2015, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



вот как с функцией прорисовки
Код

map->display_maze(0);
            
            if (map-> find_path(11, 15) == TRUE )
                printf("Success!\n");
        else
                printf("Failed\n");
             
    map->display_maze(0);


Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  Безымянный2.png 152,77 Kb
PM MAIL   Вверх
math64
Дата 2.11.2015, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



displayMaze() инициализирует массив TileMap из levelsMap:
Код

    std::cout << "MAZE:" << std::endl;
    for( int i=0; i < Map::HEIGHT_MAP; i++)
    {
       TileMap[i] = levelsMap[level][i];
       std::cout << TileMap[i] << std::endl;
    }

Естественно, если какой-то путь был посчитан, здесь он затирается.
PM   Вверх
lenarano
Дата 2.11.2015, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



А как это изменить? Я планирую эту функцию использовать для того, что бы видеть прорисовку моего пути, т.е. нужно, чтобы массив мог видоизменяться?

Добавлено через 11 минут и 59 секунд
Еще хотела спросить. У меня сейчас видно, что я просто обозначила на карте где буднт прорисовываться 'G' и 'S' и я по этому алгоритму прорисовываю свой путь. Вот кусочек кода с прорисовкой и реализацией алгоритма поиска пути
Код

void Map::display_maze( int level)
{
    int i;
    printf("MAZE:\n");
    for(int i=0; i < Map::HEIGHT_MAP; i++)
    {TileMap[i] = levelsMap[level][i];
    std::cout<<levelsMap[level][i];
    std::cout << std::endl;
    }
 
    return;
}


int Map::find_path(int x, int y)
{
        // Если x,y находится за пределами лабиринта, вернуть false.
        if ( x < 0 || x > WIDTH_MAP - 1 || y < 0 || y > HEIGHT_MAP - 1 ) return FALSE;

        // Если x,y-это цель, возвратите True.
        if ( TileMap[y][x] == 'G' ) return TRUE;

        // Если x,y не открыть, вернуть false.
        if ( TileMap[y][x] != ' ' && TileMap[y][x] != 'S' ) return FALSE;

        // + часть решения, пути.
        TileMap[y][x] = '+';

        // If find_path North of x,y is true, return true.
        if ( find_path(x, y - 1) == TRUE ) return TRUE;

        // If find_path East of x,y is true, return true.
        if ( find_path(x + 1, y) == TRUE ) return TRUE;

        // If find_path South of x,y is true, return true.
        if ( find_path(x, y + 1) == TRUE ) return TRUE;

        // If find_path West of x,y is true, return true.
        if ( find_path(x - 1, y) == TRUE ) return TRUE;

        // Снять х,Y как часть решения, пути.
        TileMap[y][x] = 'x';

        return FALSE;
}





Теперь я хочу перейти к следующему этапу, когда 
Этaп построения мaршрутa перемещения. Присвaивaем переменным Х и Y знaчения координaт стaртовой позиции. 
Т.е. я хочу передать координаты врага и пакмана и нарисовать на их месте на карте 'S'и 'G' , а не прорисовывать их на карте. Все эти изменения сейчас пытаюсь сделать.
Вот мой класс героя
Код

#ifndef PLAYER_H
#define PLAYER_H



#include "Entity.h"
#include "View.h"
//#include "map.h"


class Player:public Entity{
private:
int m_health;
int m_counter;
int m_createObjectForMapTimer;
int m_counterBonus;
int m_counterGoldIngot;
float m_currentFrame;
bool m_killer;
bool m_bonus;
std::shared_ptr<sf::View> m_view;
Map* m_map;

public:
        
    Player(Map* map,std::shared_ptr<sf::View> view, sf::Image &image,sf::String Name,float X, float Y, float W, float H);

    int getHealth (Player &p) const;
    void setHealth(Player &p, int a);
    int getCounterBonus (Player &p) const;
    void multiplyCounterBonus(Player &p, int a);
    int getCounterGoldIngot(Player &p) const;
    int getKiller(Player &p) const;
    void control();
    void update(float time);
    void interactionWithMap();
    void randomMapGenerate();
    //float GetPlayercoordinateX(){return x;}
    //float GetPlayercoordinateY(){return y;}

    
};



#endif PLAYER_H

#include "Player.h"
#include "map.h"
#include <SFML/Graphics.hpp>





Player::Player(Map* map,std::shared_ptr<sf::View> view, sf::Image &image,sf::String Name,float X, float Y, float W, float H):Entity(image, Name, X,Y,W,H){
    m_view = view;    
    m_map=map;
    m_health=3,
        m_counter=0,
        m_createObjectForMapTimer=0,
        m_counterBonus=0,
        m_counterGoldIngot=3,
        m_currentFrame=3;
    m_killer=false;
    m_bonus=false;
    state=stay;//инициализировали
    if (name == "Player1"){sprite.setTextureRect(sf::IntRect(99,224,w,h));}//если герои от уровня к уровню будут разные    
}

int Player::getHealth (Player &p) const {return p.m_health;}

void Player::setHealth(Player &p, int a){p.m_health += a;}

int Player::getCounterBonus (Player &p) const {return p.m_counterBonus;}

void Player::multiplyCounterBonus(Player &p, int a){p.m_counterBonus *= a;}

int Player::getCounterGoldIngot(Player &p) const {return p.m_counterGoldIngot;}

int Player::getKiller(Player &p) const {return p.m_killer;}

void Player::control()
{
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){state=left; speed=0.1;}
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){state=right;speed=0.1;}
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){state=up; speed=0.1;}
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){state=down;speed=0.1;}
}


void Player::interactionWithMap()
{
    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;}
            }

            if (m_map->TileMap[i][j] == 't')
            {
                x=830; y=390;
            }

            if (m_map->TileMap[i][j] == 'T')
            {
                x=50; y=390;
            }

            if (m_map->TileMap[i][j] == 'm')
            {
                m_counterGoldIngot--;
                m_map->TileMap[i][j] = ' ';

            }

            if (m_map->TileMap[i][j] == 's')
            {
                m_killer=true;
                m_map->TileMap[i][j] = ' ';
            }

            if (m_map->TileMap[i][j] == 'f')
            {
                m_bonus=false;
                m_counterBonus+=100;
                m_map->TileMap[i][j] = ' ';
            }
        }

}    

void Player::randomMapGenerate(){//рандомно расставляем камни

    int randomElementX = 0;//случайный элемент по горизонтали
    int randomElementY = 0;//случ эл-т по вертикали
    srand(time(0));//рандом    
    int countStone = 1;//количество камней

    while (countStone>0){
        randomElementX = 1 + rand() % (m_map->WIDTH_MAP - 1);//рандомное по иксу от 1 до ширина карты-1, чтобы не получать числа бордюра карты
        randomElementY = 1 + rand() % (m_map->HEIGHT_MAP - 1);//по игреку так же

        if (m_map->TileMap[randomElementY][randomElementX] == ' ')   {//если встретили символ пробел, 
            m_map->TileMap[randomElementY][randomElementX] = 'f'; //то ставим туда яблоко
            countStone--;
            m_bonus=true;
        }
    }    
}


void Player::update(float time)
{
    control();
    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;
    default: dx=0; dy=0;//case stay:break;
    }
    x+=dx*time;
    y+=dy*time;
    speed=0;
    sprite.setPosition(x+w/2,y+h/2);
    interactionWithMap();
    //////////анимация
    m_currentFrame+=0.005*time;
    if (m_currentFrame>6) m_currentFrame-=3;
    if (dx > 0) sprite.setTextureRect(sf::IntRect(31.2*int (m_currentFrame),192,32,32));
    if (dx < 0) sprite.setTextureRect(sf::IntRect(33*int (m_currentFrame),160,32,32));
    if (dy > 0) sprite.setTextureRect(sf::IntRect(32 *int(m_currentFrame),128,32,32));
    if (dy < 0) sprite.setTextureRect(sf::IntRect(32.9*int (m_currentFrame),224,32,32));
    if(m_counterGoldIngot<=0){m_map->setLevel(+1);m_counterGoldIngot=3;x=460;y=720;}
    if(m_killer==true)
    {   sprite.setColor(sf::Color::Red);
    m_counter += time;
    if(m_counter>10000){m_killer=false;m_counter=0; sprite.setColor(sf::Color::White);}
    }
    if(m_counterBonus>=1000){ m_health ++;m_counterBonus=0;}

    if (m_bonus==false){
        m_createObjectForMapTimer += time;//наращиваем таймер
        if (m_createObjectForMapTimer>10000)
        {
            randomMapGenerate();//генерация случ камн
            m_createObjectForMapTimer = 0;//обнуляем таймер
        }
    }
    if (life) 
    {
        GetPlayerCoordinateForView(m_view, sprite.getPosition().x,sprite.getPosition().y);
    }

}






и Врага
Код

#ifndef ENEMY_H
#define ENEMY_H

#include "Entity.h"




class Enemy:public Entity{
private:
        Map* m_map;
public:
    int zq,timer;
    float CurrentFrame;
    
    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;
        zq=1;state=left;timer=0;CurrentFrame=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();
           /* m_map->display_maze(0);
            
             if ( m_map->find_path(11, 15) == TRUE )
                printf("Success!\n");
        else
                printf("Failed\n");
            ;    
        //    m_map->display_maze(0);*/
            
     
            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));
        }
    }



};




#endif ENTITY_H






В main в обработчике событий я хочу в обработчике событий передать эти координаты

Код

Player pacman(map,view, heroimage,"Player1",460,730,32.0,32.0);//передаем координаты прямоугольника player из карты в координаты нашего игрока

    std::list<Entity*> entities;//список,куда будем бросать объекты
    std::list <Entity*>::iterator it;//итератор, чтобы проходить по элементам списка
    std::list <Entity*>::iterator it2;//враг-враг
    
    
    entities.push_back(new Enemy(map,easyEnemyImage,"EasyEnemy",410,290,32.0,32.0));
    //entities.push_back(new Enemy(map,easyEnemyImage,"EasyEnemy",425,290,32.0,32.0));
    //entities.push_back(new Enemy(map,easyEnemyImage,"EasyEnemy",440,190,32.0,32.0));

..........

for (it = entities.begin(); it != entities.end(); it++)//проходимся по эл-там списка
        {   
            if ((*it)->name=="EasyEnemy")
            { 
                //  int i=int(pacman.x);
               // int j=int(pacman.y);
                (*it)->getPlayerCoord(pacman.x,pacman.y);
                //  map->TileMap[i][j] = 'G';
                //  map->TileMap[int((*it)->x)][int((*it)->y)] = 'S';
                if (((*it)->x-pacman.x<55)&&((*it)->y>pacman.y))  {(*it)->dy=-0.5,(*it)->dx=0;} 
                if (((*it)->x-pacman.x<54)&&((*it)->y<pacman.y)) {(*it)->dy=0.5,(*it)->dx=0;}
                if ((pacman.y-(*it)->y<53)&&((*it)->x<pacman.x)) {(*it)->dx=0.5,(*it)->dy=0;}
                if (((*it)->y-pacman.y<56)&&((*it)->x>pacman.x)) {(*it)->dx=-0.5,(*it)->dy=0;}
            }







Что я тут делаю не так? Почему выдается ошибка, программа не запускается. Хочу добиться прорисовки дорожки от девочки к дракону. 

PM MAIL   Вверх
math64
Дата 2.11.2015, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Ну, я бы не стал портить карту во время поиска пути.
Код

struct Point { int x, int y};
std::list<Point> find_path(const Point& start);
std::list<Point> find_path(int x, int y) { Point start = { x, y }; return find_path(start); }

find_path() возвращает пустой список если путь не найден.
Если путь будет найден - его можно будет отобразить на карте.
При рекурсивном поиске пути нужно помечать, где уже были, чтобы не возвращаться. Делаем это на временной карте:
Код

enum flag {
  free, // свободно
  wall, // стенка
  startpoint, // начало пути
  endpoint, // конец пути
  inpath, // в пробном пути
  noway, // проверено, что ведет в тупик
  ...
};
std::list<Point> find_path(const Point& start) {
  flag tempMap[HEIGHT_MAP][WIDTH_MAP];
  for(int y =0; y < HEIGHT_MAP; y++)
    for(int x =0; x < WIDTH_MAP; x++)
        tempMap[y][x] = free; // или wall - см. оригинальную карту
  tempMap[start.y][start.x] = startpoint;
  return find_path(const Point& start, tempMap); // Вызываем рекурсивную функцию
}

PM   Вверх
math64
Дата 2.11.2015, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



PS: значения flag лучше задавить степенями двойки:
Код

enum flag {
  free = 0, // свободно
  wall = 1, // стенка
  gold = 2, // золото
  enemy = 4, // враг
  startpoint = 8, // начало пути
  endpoint = 16, // конец пути
  inpath = 32, // в пробном пути
  noway = 64, // проверено, что ведет в тупик
  ...
};

Тогда можно задавать комбинации значений:
Код

gold | enemy; // золото, охраняемое врагом
gold | inpath; // путь через клетку с золотом

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


Шустрый
*


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

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



Не поняла((
У нас есть
 struct Point { int x, int y};
std::list<Point> find_path(int x, int y) { Point start = { x, y }; return find_path(start); }
Я должна это добавить в класс врага?
Я в листе информация о передвижении моего врага, т.е. где он находится?

А потом в классе карта я работаю уже
std::list<Point> find_path(const Point& start); передаю координаты врага 
enum flag {
  free, // свободно
  wall, // стенка
  startpoint, // начало пути
  endpoint, // конец пути
  inpath, // в пробном пути
  noway, // проверено, что ведет в тупик
  ...
};

и реализация в cpp/ файле?
std::list<Point> find_path(const Point& start) {
  flag tempMap[HEIGHT_MAP][WIDTH_MAP];
  for(int y =0; y < HEIGHT_MAP; y++)
    for(int x =0; x < WIDTH_MAP; x++)
        tempMap[y][x] = free; // или wall - см. оригинальную карту
  tempMap[start.y][start.x] = startpoint;
  return find_path(const Point& start, tempMap); // Вызываем рекурсивную функцию
}
PM MAIL   Вверх
lenarano
Дата 2.11.2015, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Ребята, вы меня конечно извините, что туплю. У меня уже с этим курсовым скоро крыша поедет. Варюсь в собственном соку-так получилось. Деваться некуда -стараюсь делать, а знаний и умений мало. Вот как мне оживить моих врагов. 
math64, вот вы мне показали, а я не могу понять куда, что всунуть и до конца, что где обозначает. 
Вот мои основные классы , которые тут нужны. Карта, враг, герой. Что мне добавить куда и как вставить, чтобы мои враги поумнели и карту  я увидела.
Код

#ifndef MAP_H
#define MAP_H


#define FALSE 0
#define TRUE 1

#include <SFML\Graphics.hpp>



class Map{
private:
int m_level;

public: 
   enum { HEIGHT_MAP=25, WIDTH_MAP=28 };
   sf::String TileMap[HEIGHT_MAP];
   static const char* levelsMap[][HEIGHT_MAP];
  

 Map();
 
 int getLevel();

 void setLevel(int level);

 void display_maze( int level);

 int find_path(int x, int y);

};

 
#endif

#include "map.h"

#include <iostream>

const char * Map::levelsMap[][Map::HEIGHT_MAP] = {
        { 
                "0000000000000000000000000000",/* Инициализация 0-го уровня */
                "0   S                      0",
                "0                          0",
                "0  0 s0   0      0   0s 0 G0",
                "0  0000   0mmmmmm0   0000  0",
                "0  0mm0   00000000   0mm0  0",
                "0                          0",
                "0                          0",
                "0  0mm0   000  000   0mm0  0",
                "0  0000   0      0   0000  0",
                "0  0mm0   0      0   0mm0  0",
                "t         000  000         T",
                "t                          T",
                "t                          T",
                "0  0mm0   00000000   0mm0  0",
                "0  0000              0000  0",
                "0  0mm0              0mm0  0",
                "0         00000000         0",
                "0                          0",
                "0  0mm0              0mm0  0",
                "0  0000   00000000   0000  0",
                "0  0 s0              0s 0  0",
                "0                          0",
                "0                          0",
                "0000000000000000000000000000"},
            {"0000000000000000000000000000", /* Инициализация 1-го уровня */ 
            "0                          0",
            "0                          0",
            "0  0                    0  0",
            "0  0000              0000  0",
            "0  0      000  000      0  0",
            "0         0      0         0",
            "0         0      0         0",
            "0  0mm    000  000    mm0  0",
            "0  0000              0000  0",
            "0  0                    0  0",
            "t         00000000         T",
            "t           m00m           T",
            "t           m00m           T",
            "0  0      00000000      0  0",
            "0  0000              0000  0",
            "0  0                    0  0",
            "0                          0",
            "0      0000      0000      0",
            "0  0      0s    s0      0  0",
            "0  0  0   00000000   0  0  0",
            "0  0  0   0mmmmmm0   0  0  0",
            "0                          0",
            "0                          0",
            "0000000000000000000000000000"}
    };

Map::Map()
{
        setLevel(0);
    
}

int Map:: getLevel() { return m_level; }

void Map:: setLevel(int level)
{
    
    int levelsCount = sizeof(levelsMap) / (Map::HEIGHT_MAP * sizeof(char *));

    if (level < 0 || level >= levelsCount)
        level = 0;
    m_level = level;
    for(int i=0; i < HEIGHT_MAP; i++)
    {TileMap[i] = levelsMap[level][i];}
}



/*void Map::display_maze( int level)
{
    int i;
    printf("MAZE:\n");
    for(int i=0; i < Map::HEIGHT_MAP; i++)
    {TileMap[i] = levelsMap[level][i];
    std::cout<<levelsMap[level][i];
    printf("\n");
    }
 
    return;
}*/


int Map::find_path(int x, int y)
{
        // Если x,y находится за пределами лабиринта, вернуть false.
        if ( x < 0 || x > WIDTH_MAP - 1 || y < 0 || y > HEIGHT_MAP - 1 ) return FALSE;

        // Если x,y-это цель, возвратите True.
        if ( TileMap[y][x] == 'G' ) return TRUE;

        // Если x,y не открыть, вернуть false.
        if ( TileMap[y][x] != ' ' && TileMap[y][x] != 'S' ) return FALSE;

        // + часть решения, пути.
        TileMap[y][x] = '+';

        // If find_path North of x,y is true, return true.
        if ( find_path(x, y - 1) == TRUE ) return TRUE;

        // If find_path East of x,y is true, return true.
        if ( find_path(x + 1, y) == TRUE ) return TRUE;

        // If find_path South of x,y is true, return true.
        if ( find_path(x, y + 1) == TRUE ) return TRUE;

        // If find_path West of x,y is true, return true.
        if ( find_path(x - 1, y) == TRUE ) return TRUE;

        // Снять х,Y как часть решения, пути.
        TileMap[y][x] = 'x';

        return FALSE;
}






Класс героя и врага в предыдущем посте.
PM MAIL   Вверх
math64
Дата 2.11.2015, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Главная идея - при поиске пути использовать временную карту.
Куда запихнуть? Можно в класс карты, можно в класс игрока (если путь ищется для игрока), можно в класс врага (если путь ищется для врага), можно в базовый класс Entity для игрока и врага (путь ищется для того и другого, в производных классах можно переоределить специфику)
показывыть путь лучше не в консоли, а в игровом окне - так нагляднее, но я не знаю возможностей вашего движка.
Реализовать можно примерно так (могут быть ошибки):
Код

std::list<Point> Map::find_path(int start_x, start_y) {
  if ( start_x < 0 || start_x > WIDTH_MAP - 1 || start_y < 0 || start_y > HEIGHT_MAP - 1 )
   return std::list<Point>(); // Empty list
  flag tempMap[HEIGHT_MAP][WIDTH_MAP];
  for(int y =0; y < HEIGHT_MAP; y++)
    for(int x =0; x < WIDTH_MAP; x++) {
       flag f;
       switch (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;
  std::list<Point> path;
  return find_path(x, y, tempMap, path); // Вызываем рекурсивную функцию
}
std::list<Point> Map::find_path(int start_x, start_y,
       flag tempMap[HEIGHT_MAP][WIDTH_MAP],
       std::list<Point> path) {
  if ( x < 0 || x > WIDTH_MAP - 1 || y < 0 || y > HEIGHT_MAP - 1 )
   return std::list<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::list<Point>();
  // Мы сдесь уже были
  if ( (tempMap[y][x] & (inpath|noway)) != 0)
    return std::list<Point>();
  tempMap[y][x] |= inpath; // + часть решения, пути.
  // If find_path North of x,y is true, return true.
  std::list<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] &= ~inpath;
  tempMap[y][x] |= noway;
  return std::list<Point>();
}


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


Шустрый
*


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

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



Оставила в классе Map только прорисовку карты. Решила реализовать в классе Врага, т.к. он преследует героя.
Код

#ifndef ENEMY_H
#define ENEMY_H

#include "Entity.h"




class Enemy:public Entity{
private:
    Map* m_map;
public:
    float CurrentFrame;
    struct Point { int x; int y;};
    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=left;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"){//для персонажа с таким именем логика будет такой

            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::list<Point> find_path(int start_x, int start_y) {//идентификатор start_y не определен
        if ( start_x < 0 || start_x > m_map->WIDTH_MAP - 1 || start_y < 0 || start_y >  m_map->HEIGHT_MAP - 1 )//идентификатор start_y не определен
            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;
            std::list<Point> path;
            return find_path(x, y, tempMap, path); // Вызываем рекурсивную функцию
    }

    std::list<Point> find_path(int start_x, int start_y,flag tempMap[Map::HEIGHT_MAP][Map::WIDTH_MAP],std::list<Point> path) {
            if ( x < 0 || x > m_map->WIDTH_MAP - 1 || y < 0 || y > m_map->HEIGHT_MAP - 1 )
                return std::list<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::list<Point>();
            // Мы здесь уже были
            if ( (tempMap[y][x] & (inpath|noway)) != 0)
                return std::list<Point>();
            tempMap[y][x] |= inpath; // + часть решения, пути.
            // If find_path North of x,y is true, return true.
            std::list<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] &= ~inpath;
            tempMap[y][x] |= noway;
            return std::list<Point>();
    }


};

#endif ENTITY_H








Компилятор ругается на эти строки, подчеркивая переменную y.(в последней функции)
if ( (tempMap[y][x] & endpoint) != 0) return path;
if ( (tempMap[y][x] & wall) != 0)
if ( (tempMap[y][x] & (inpath|noway)) != 0)
и т.д.
Пишет:
 выражение должно относиться к целочисленному типу или типу перечисления без области видимости    
индекс имеет нецелый тип    




Посмотрите правильно ли я все остальное указала. Но вроде больше ошибок нет.

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


Эксперт
****


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

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



Ну, можно было заметить мою ошибку (предупреждал, что могут быть). Параметры функции - start_x и start_y, а внутри функции - x и y.
Если будет ругаться на tempMap[y][x] &= ~inpath;
придется писать tempMap[y][x] = (flag)(tempMap[y][x]&~inpath); или объявить int tempMap[HEIGHT_MAP][WIDTH_MAP].

Относительно того как показывать результат поиска пути.
В подобных библиотеках обычно имеется возможность работать со слоями (Layer)
Карту нужно разбить на слои:
1. собственно карта - стены и проходы
2. неподвижные объекты - золото
3. подвижные объекты - спрайты - игрок и враги
4. слой отладки - в нем и выводить найденный путь.
5. Слой надписей (GAME OVER)

PM   Вверх
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   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

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

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

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

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


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

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


 




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


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

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