@MartMax27
Junior

Почему не работает sprite (SFML) у объекта в векторе?

Всем привет) Пожалуйста, помогите разобраться. Кратко расскажу в чём дело. В учебных целях делаю игру Arkanoid на SFML. Сделал простенький вариант с счётчиком очков, уровня. Из объектов (structur) шарик, платформа и кирпичики. Вот в последних вся проблема. Решил сделать у них sprite, чтоб красиво было. Не поучилось. Посидел ещё. В итоге сделал sprite для платформы, а кирпичи не получаются. Точнее они рисуются коряво. Возможно проблема в initBricks, а именно в моменте заполнения вектора bricks
За ранние извиняюсь за говно код) Все картинки хранятся в images в одной директории с исходным кодом
5de52765e10fc035582814.png
5de5277270be4187386030.png
5de52682023a2429579808.png
//RenderWindow window(VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Arkanoid");
/*
	Реализована пауза при нажатии на пробел
	Подсчёт очков
*/
#include <SFML/Graphics.hpp>
#include <iostream>
#include <cmath>

using namespace std;
using namespace sf;

constexpr int WINDOW_WIDTH{ 800 }, WINDOW_HEIGHT{ 600 };
constexpr float BULL_RADIUS{ 10.f }, BALL_VELOCITY{ 200.f };
constexpr float PABBLE_WIDTH{ 60.f }, PABBLE_HEIGHT{ 20.f }, PABBLE_VELOCITY{ 200.f };
constexpr float BLOCK_WIDTH{ 60.f }, BLOCK_HEIGHT{ 20.f };
constexpr int COUNT_BLOCKS_X{ 11 }, COUNT_BLOCKS_Y{ 4 };
const string IMG_PADLE{ "images/paddle.png" }, IMG_BRICK{ "images/brick_01.png" };

struct Ball
{
	CircleShape shape;
	Vector2f velocity{ -BALL_VELOCITY, -BALL_VELOCITY };
	bool lost{ false };

	Ball(float mX, float mY)
	{
		shape.setPosition(mX, mY);
		shape.setRadius(BULL_RADIUS);
		shape.setFillColor(Color::White);
		shape.setOrigin(BULL_RADIUS, BULL_RADIUS);
	}

	void lostTheBall(bool &lost)
	{
		lost = !lost;
		cout << "Game over!" << endl;
	}

	void update(const float dt)
	{
		Vector2f position = shape.getPosition();
		position += velocity * dt;

		if ((position.x + BULL_RADIUS >= WINDOW_WIDTH) && (velocity.x > 0))
			velocity.x = -velocity.x;
		if ((position.x - BULL_RADIUS < 0) && (velocity.x < 0))
			velocity.x = -velocity.x;
		if ((position.y + BULL_RADIUS >= WINDOW_HEIGHT) && (velocity.y > 0))
		{
			velocity.y = -velocity.y;
			lostTheBall(lost);
		}
		if ((position.y - BULL_RADIUS < 0) && (velocity.y < 0))
			velocity.y = -velocity.y;
		shape.setPosition(position);
	}

	float sideLeft() { return shape.getPosition().x - shape.getRadius(); }
	float sideRight() { return shape.getPosition().x + shape.getRadius(); }
	float sideUp() { return shape.getPosition().y - shape.getRadius(); }
	float sideBown() { return shape.getPosition().y + shape.getRadius(); }
};

struct Paddle
{
	Texture texture;
	Sprite sprite;
	Vector2f velocity;

	Paddle(const string &path, float mX, float mY)
	{
		if (!texture.loadFromFile(path))
		{
			cout << "Error loading file" << endl;
			exit(1);
		}
		texture.setSmooth(true);
		sprite.setTexture(texture);
		sprite.setPosition(mX, mY);
		Rect<float> size = sprite.getGlobalBounds();
		sprite.setOrigin(Vector2f(size.width / 2, size.height / 2));
	}

	void update(const float dt)
	{
		Vector2f position = sprite.getPosition();
		position += velocity * dt;
		float step = sprite.getOrigin().x;

		if (Keyboard::isKeyPressed(Keyboard::Key::Left) && (position.x - step > 0))
			velocity.x = -PABBLE_VELOCITY;
		else if (Keyboard::isKeyPressed(Keyboard::Key::Right) && (position.x + step < WINDOW_WIDTH))
			velocity.x = PABBLE_VELOCITY;
		else
			velocity.x = 0;

		sprite.setPosition(position);
	}

	float sideLeft() { return sprite.getPosition().x - sprite.getOrigin().x; }
	float sideRight() { return sprite.getPosition().x + sprite.getOrigin().x; }
	float sideUp() { return sprite.getPosition().y - sprite.getOrigin().y; }
	float sideBown() { return sprite.getPosition().y + sprite.getOrigin().y; }
};

struct Brick
{
	Texture texture;
	Sprite sprite;
	bool destroyed{ false };

	Brick(const string &path, float mX, float mY)
	{
		if (!texture.loadFromFile(path))
		{
			cout << "Error loading file" << endl;
			exit(1);
		}
		texture.setSmooth(true);
		sprite.setTexture(texture);
		sprite.setPosition(mX, mY);
		Rect<float> size = sprite.getGlobalBounds();
		sprite.setOrigin(Vector2f(size.width / 2, size.height / 2));
	}

	float sideLeft() { return sprite.getPosition().x - sprite.getOrigin().x; }
	float sideRight() { return sprite.getPosition().x + sprite.getOrigin().x; }
	float sideUp() { return sprite.getPosition().y - sprite.getOrigin().y; }
	float sideBown() { return sprite.getPosition().y + sprite.getOrigin().y; }
};

struct Progress
{
	int playerPoints{ 0 };
	int playerLevel{ 0 };
};

struct World
{
	Ball ball{ WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 };
	Paddle paddle{ IMG_PADLE, WINDOW_WIDTH / 2, WINDOW_HEIGHT - 50 };
	Progress progress;
	vector<Brick> bricks;
	bool pause{ false };
	bool restart{ false };
};

template <class T1, class T2>
bool isIntersecting(T1 &mA, T2 &mB)
{
	//если есть пересечение, то возвращает TRUE
	return mA.sideRight() >= mB.sideLeft() && mA.sideLeft() <= mB.sideRight() &&
		mA.sideBown() >= mB.sideUp() && mA.sideUp() <= mB.sideBown();
}

void testCollision(Paddle &mPaddle, Ball &mBall)
{
	if (!isIntersecting(mPaddle, mBall))
		return;

	mBall.velocity.y = -BALL_VELOCITY;

	if (mBall.shape.getPosition().x < mPaddle.sprite.getPosition().x)
		mBall.velocity.x = -BALL_VELOCITY;
	else
		mBall.velocity.x = BALL_VELOCITY;
}

void testCollision(Brick &mBrick, Ball &mBall, Progress &mProg)
{
	if (!isIntersecting(mBrick, mBall))
		return;

	mBrick.destroyed = true;
	mProg.playerPoints += 10;
	cout << "playerPoints = " << mProg.playerPoints << endl;

	float overlapLeft{ mBall.sideRight() - mBrick.sideLeft() };
	float overlapRight{ mBrick.sideRight() - mBall.sideLeft() };
	float overlapTop{ mBall.sideBown() - mBrick.sideUp() };
	float overlapBottom{ mBrick.sideBown() - mBall.sideUp() };

	bool ballFromLeft(abs(overlapLeft) < abs(overlapRight));
	bool ballFromTop(abs(overlapTop) < abs(overlapBottom));

	float minOverlapX{ ballFromLeft ? overlapLeft : overlapRight };
	float minOverlapY{ ballFromTop ? overlapTop : overlapBottom };

	if (abs(minOverlapX) < abs(minOverlapY))
		mBall.velocity.x = ballFromLeft ? -BALL_VELOCITY : BALL_VELOCITY;
	else
		mBall.velocity.y = ballFromTop ? -BALL_VELOCITY : BALL_VELOCITY;
}

void initBricks(World &world)
{
	/*Texture brickTexture;
	brickTexture.loadFromFile(IMG_BRICK);
	brickTexture.setSmooth(true);*/
	//инициализация кирпичей
	for (int iX{ 0 }; iX < COUNT_BLOCKS_X; ++iX)
		for (int iY{ 0 }; iY < COUNT_BLOCKS_Y; ++iY)
			world.bricks.emplace_back(IMG_BRICK, (iX + 1) * (BLOCK_WIDTH + 3) + 22, (iY + 2) * (BLOCK_HEIGHT + 3));
}

void updateWorld(World &world, Clock &clock)
{
	const float deltaTime = clock.restart().asSeconds();
	if (world.pause)
		return;
	world.ball.update(deltaTime);
	world.paddle.update(deltaTime);
	testCollision(world.paddle, world.ball);
	for (auto &brick : world.bricks)
		testCollision(brick, world.ball, world.progress);

	world.bricks.erase(remove_if(begin(world.bricks), end(world.bricks), [](const Brick &mBrick) { return mBrick.destroyed; }), end(world.bricks));
}

void pollEvents(World &world, RenderWindow &window)
{
	Event event;
	while (window.pollEvent(event))
	{
		switch (event.type)
		{
		case Event::Closed:
			window.close();
			break;
		case Event::KeyPressed:
			if (event.key.code == Keyboard::Space)
				world.pause = !world.pause;
			break;
		default:
			break;
		}
	}
}

void redrawWorld(World &world, RenderWindow &window)
{
	window.setFramerateLimit(60);
	window.clear(Color::Black);
	window.draw(world.ball.shape);
	window.draw(world.paddle.sprite);
	for (auto &brick : world.bricks)
		window.draw(brick.sprite);
	window.display();
}

int main()
{
	ContextSettings settings;
	settings.antialiasingLevel = 8;
	RenderWindow window(VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Arkanoid");
	Clock clock;

	World world;
	initBricks(world);

	while (window.isOpen())
	{
		pollEvents(world, window);
		updateWorld(world, clock);
		redrawWorld(world, window);
	}
	return 0;
}
  • Вопрос задан
  • 150 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы