SFML и C++ Уроки \ Разработка игр › Форумы › SFML Graphics › Контейнеры в классе
В этой теме 11 ответов, 4 участника, последнее обновление Павел Букреев 7 года/лет, 9 мес. назад.
-
АвторСообщения
-
Хочу реализовать контейнеры в классе, но не всё хочет работать, и выдаёт ошибку при компиляции.
C++123456789101112131415161718192021222324#pragma once#include<SFML/Graphics.hpp>#include<cmath>#include<list>class Polygon{public:Polygon(int Vertex, float X, float Y, float Radius, int Elements);virtual void Draw(sf::RenderWindow &window);virtual void Update(float &time);~Polygon();private:std::list<sf::CircleShape*> p;std::list<sf::CircleShape*>::iterator it;//sf::Texture texture;//sf::String png;int element;int vertex;float scale;float radius;float x, y;};C++12345678910111213141516171819202122232425262728293031323334353637383940414243#include"Polygon.h"#include<iostream>#define PI 3.1415926Polygon::Polygon(int Vertex, float X, float Y, float Radius, int Elements){element = Elements;vertex = Vertex;radius = Radius;scale = 1.0;x = X;y = Y;for( int i = 0; i < element; ++i )p.push_back(new sf::CircleShape(radius, vertex));for(it = p.begin(); it != p.end(); it++){(*it)->setRadius( radius );(*it)->setPointCount( vertex );(*it)->setPosition( x, y );(*it)->setOrigin( radius, radius );(*it)->setScale( scale, scale );(*it)->setOutlineThickness( 10 );(*it)->setOutlineColor( sf::Color( 255, 0, 255 ));(*it)->setFillColor( sf::Color( 0, 255, 255 ));}}void Polygon::Draw(sf::RenderWindow &window){for( it = p.begin(); it != p.end(); it++ ){(*it)->draw( window ); //Ошибка компиляцииwindow.draw(*it); //Ошибка компиляции}}void Polygon::Update(float &time){(*it)->rotate( 0.05*time );}Polygon::~Polygon(){}Попробуй по отдельности, сначала без (*it)->draw( window ); потом без window.draw(*it);
И напиши свою ошибку, что компилятор говорит.
Переименуй свой класс он с чем то конфликтует. Даже без отрисовки мне выдает :Expression: list iterator not dereferencable. Гугл дал результат о том что итератор выходит за рамки массива. Сам с этим сталкивался.
Причина: невозможно преобразовать “sf::CircleShape *” в “const sf::Drawable &”
Ни один конструктор не смог принять исходный тип, либо разрешение перегрузки конструктора неоднозначно.Надеюсь кто нибудь даст ответ ). Самому интересно как это решить.
Я по этому написал сразу 2, потому что ни один не работает) да и вообще не компилируется
C++12(*it)->draw( window ); //Ошибка компиляцииwindow.draw(*it); //Ошибка компиляцииБез отображения проект компилируется, но при запуске выбивает ошибку.
Debug Assertion Failed!
Program: …путь\MSVCP110D.dll
File: …путь\include\list Line: 210Expression: list iterator not dereferencable
For information on how your programm can cause an assertion failure, see the Visual C++ documentation asserts.(Press retry to debug the Application)
Когда создаю лист объектов вне класса, то работает как нужно. Но код от этого становится неприятным.
Попробую сделать через наследование.
Как я понял для отрисовки итератор должен представлять собой силку на объект. Компиль мне об этом говорит прямо, что метод draw() требует силку. По поводу выхода итератора за приделы я так и не чего толкового не нашел.
вызываешь draw, который у тебя в классе не описан.
C++1(*it)->draw( window ); //Ошибка компиляциипросто так рисовать через итератор у тебя не получится, ты должен рисовать спрайт объекта списка.
C++1window.draw(*it); //Ошибка компиляциивспомни, мы ведь в int main не рисуем объект player, мы рисуем только его спрайт.
Я думаю сможешь нарисовать так, как написал draw(*it) только если закинешь в список одни лишь спрайты.
Чтобы нарисовать объект – тебе нужен спрайт.
Чтобы вызвать функцию (метод) (или обратиться к свойству) объекта нужно пройтись итератором по эл-там списка и вызвать её так: (*it)->функция();
Далее приведу отрывки переписки с Heisenberg’ом в вконтакте, чтобы другие тоже знали.
Итератор нужен для прохождения по элементам списка. И у всех элементов должна быть ф-ция, которую ты вызываешь (или у их базового класса), иначе скажет, что такой ф-ции или переменной нету.
Список хранит в себе объекты, итератор пробегается от начала до конца. В каждом элементе списка есть адрес на следующий элемент (такая конструкция называется односвязный или однонаправленный список). Когда ты захочешь удалить элемент посередине списка – адресация от предыдущего элемента направится с предыдущего от удаленного, на следующий к удаленному. Например в списке лежат объекты 1->2->3 , удалишь 2 будет 1->3. Очень удобно удалять, например пули в игре. Если удаляешь с вектора, то нужно будет вынуть и назад запихнуть из него элементы. Поэтому тут список лучше.
и в списке нельзя обращаться по индексу к элементу, поэтому прём итератором.
и нам не надо писать кучу строк типа player1.update();
player2.update(); и тд
а просто закинуть в список плеер и вызывать it->update()Как понял у него sf::CircleShape и он может рисовать через window.draw(*it);
У меня объект игрок унаследован от класса Animation, а Animation унаследовано от Drawble . Я могу спокойно рисовать своего игрока или моба с помощью window.draw();
А по поводу того что итератор выходит за рамки, как это лечить ?
ошибка скорее всего в том, что вы не правильно используете передачу окна в функцию и/или не правильно его используете в самой функции.
Когда я делал свою игру, то вот так сделал:
в main.cpp
game->draw(&window);
// передаю ссылку на окно
в Game.cpp
void Game::draw(sf::RenderWindow *window)
{ // отрисовка игры
if( numSpaceShip != 0 )
for(std::vector<SpaceShip*>::iterator it = vecSpaceShip.begin(); it != vecSpaceShip.end(); ++it)
if( (*it)->getIsActivity() == true )
(*it)->draw(window);
}// передаю эту же ссылку в экземпляр класса КосмическийКорабль
SpaceShip.cpp
void SpaceShip::draw(sf::RenderWindow *window)
{
(*window).draw(sprite);// а тут получаю окно, и использую метод draw()
}о векторе можете почитать тут http://cppstudio.com/post/8453/
Спасибо, но это давно решённая проблема.
Всё равно спасибо. Кому нибудь пригодится.
А если проблема решена – надо отписаться об этом 😉 -
АвторСообщения
Для ответа в этой теме необходимо авторизоваться.