Indexing Issue

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
Empirean
Posts: 26
Joined: September 24th, 2017, 3:23 am

Indexing Issue

Post by Empirean » September 26th, 2017, 2:05 pm

Hi, I wrote the code below and somehow it's misbehaving. I checked the code in debug and i cant seem to find what's wrong with it. The indexing looks "okay" to me but I'm still getting unexpected results. There is this one rectangle that is misbehaving. I've tested everything and i can confirm that the bug only occurs when i add the indexing part of the code.

Game.cpp

Code: Select all

#include "MainWindow.h"
#include "Game.h"

Game::Game( MainWindow& wnd )
	:
	wnd( wnd ),
	gfx( wnd ),
	rng(std::random_device()())
{
	for (int i = 0; i < maxEnemy; i++)
	{
		enemy[i] = Enemy(0, 0);
	}

}

void Game::Go()
{
	gfx.BeginFrame();	
	UpdateModel();
	ComposeFrame();
	gfx.EndFrame();
}

void Game::UpdateModel()
{
	for (int i = 0; i < index; i++)
	{

		if (enemy[i].isDestroyed())
		{
			enemy[i] = enemy[index];
			index--;
			i--;
		}
		else
		{
			enemy[i].update();
		}
	}
	registerEnemy();	
	
}

void Game::registerEnemy()
{
	if (timeLeft > 0)
	{
		timeLeft--;
	}
	else
	{
		timeLeft = maxTime;
		if (index < maxEnemy)
		{
			std::uniform_int_distribution<int> yDist(0, Graphics::ScreenHeight - 30);
			index++;
			enemy[index].moveTo(Graphics::ScreenWidth, yDist(rng));
			
		}
	}
}


void Game::ComposeFrame()
{
	for (int i = 0; i < index; i++)
	{
		if (!enemy[i].isDestroyed())
		{
			enemy[i].draw(gfx);
		}
	}
}
Game.h

Code: Select all

class Game
{
public:
	Game( class MainWindow& wnd );
	Game( const Game& ) = delete;
	Game& operator=( const Game& ) = delete;
	void Go();
private:
	void ComposeFrame();
	void UpdateModel();
	/********************************/
	/*  User Functions              */
	void registerEnemy();
	/********************************/
private:
	MainWindow& wnd;
	Graphics gfx;
	/********************************/
	/*  User Variables              */
	static constexpr int maxEnemy = 30;
	int index = 0;
	Enemy enemy[maxEnemy];
	std::mt19937 rng;
	int timeLeft = 0;
	int maxTime = 10;
	/********************************/
};
Enemy.cpp

Code: Select all

Enemy::Enemy(int x, int y)
{
	_x = x;
	_y = y;
}

void Enemy::moveTo(int x, int y)
{
	_x = x - _width;
	_y = y;
	_destroyed = false;
}

void Enemy::destroy()
{
	_destroyed = true;
	_x = 0;
	_y = 0;
}


bool Enemy::isDestroyed()
{
	return _destroyed;
}

void Enemy::update()
{
	if (_x - _speed <= 0)
	{
		destroy();
	}
	else
	{
		_x = _x - _speed;
	}
}

void Enemy::draw(Graphics& gfx)
{
	gfx.DrawRectDim(_x, _y, _width, _height, _c);
}
Enemy.h

Code: Select all

class Enemy
{
private:
	int _x;
	int _y;
	bool _destroyed = true;
	Color _c = Colors::Green;
	static constexpr int _width = 20;
	static constexpr int _height = 20;
	static constexpr int _speed = 7;
	void destroy();
public:
	Enemy() = default;
	Enemy(int x, int y);

	void moveTo(int x, int y);
	bool isDestroyed();
	void update();
	void draw(Graphics& gfx);

};
Thank you in advance for the response. Oh, and sometimes it messes up my other objects. My other objects are working fine though. The above code produces the attached executable ((.exe) insize the zip file), it bugs so that's that.
Attachments
Engine.zip
(124.25 KiB) Downloaded 110 times

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: Indexing Issue

Post by chili » September 26th, 2017, 3:37 pm

Hey bro, I'm going on a trip for a couple of days. Hopefully somebody hooks you up with an answer soon, but if not I will check this out on the weekend.
Chili

User avatar
SlevinKelevra
Posts: 80
Joined: September 9th, 2013, 12:58 am
Location: Germany

Re: Indexing Issue

Post by SlevinKelevra » September 26th, 2017, 4:56 pm

Hey Empirean. Which repository did you clone? I cannot find the DrawRectDim function (neither in chili_framework nor in sprite).
Carpe noctem

User avatar
SlevinKelevra
Posts: 80
Joined: September 9th, 2013, 12:58 am
Location: Germany

Re: Indexing Issue

Post by SlevinKelevra » September 26th, 2017, 5:05 pm

Ok, I have added another drawRect function to check your code. So what exaclty is your problem? is it that "blinking" rectangle?
Carpe noctem

User avatar
SlevinKelevra
Posts: 80
Joined: September 9th, 2013, 12:58 am
Location: Germany

Re: Indexing Issue

Post by SlevinKelevra » September 26th, 2017, 5:34 pm

Ok, I think I found the bug.

First of all you should increment your index after you call moveTo in the registerEnemy function:

Code: Select all

        if( index < maxEnemy )
        {
            std::uniform_int_distribution<int> yDist( 0, Graphics::ScreenHeight - 30 );
            enemy[ index ].moveTo( Graphics::ScreenWidth, yDist( rng ) );
            index++;
        }
so that you move your first enemy in the array, then the second etc.

Secondly you should decrement index before assigning an existing enemy to a desroyed position in updateModel:

Code: Select all

        if( enemy[ i ].isDestroyed() )
        {
            index--;
            enemy[ i ] = enemy[ index ];
            i--;
        }
This should solve your problem.

BR
Slevin
Carpe noctem

Empirean
Posts: 26
Joined: September 24th, 2017, 3:23 am

Re: Indexing Issue

Post by Empirean » September 26th, 2017, 9:39 pm

@chili: have fun bro. Btw i didnt use std::vectors yet since the implementation will be the same. I dont think i should skip tutorials. Stay safe.

@SlevinKelevra:first of all, thank you for looking up my code. I didnt clone any repository. I just grabbed the framework from tutorial 0 then added my stuff. Oh, yeah i forgot to add the code for my drawrectdim. The code is identical to the tutorial. I forgot which one. Yup, its the blinking rectangle.

Im on my phone right now so please understand why im not quoting.
The first solution, that was the remnant of my revision. I must have forgotten to move the index increment under the moveto(). It gives a different bug when i do that but ill try to really organize the semantics of my code. The second solution, i think its ok. What it does is, it puts the Enemy on the last used index to the index of the destroyed index. I think its working just fine.

I will try to post what happens when when i implement the first solution. Thanks again for checking my code SlevinKelevra.

User avatar
SlevinKelevra
Posts: 80
Joined: September 9th, 2013, 12:58 am
Location: Germany

Re: Indexing Issue

Post by SlevinKelevra » September 26th, 2017, 9:48 pm

You need to change both things, there is no first or second solution. Try it out, it should work.
Carpe noctem

Empirean
Posts: 26
Joined: September 24th, 2017, 3:23 am

Re: Indexing Issue

Post by Empirean » September 26th, 2017, 10:33 pm

I havent tried it. I get what you mean now. I just realized that im incrementing index in advance for my loops to work and forgot that deindexing the max index is refering to the index of an unused array. Thank you so much. SlevinKelevra.

Post Reply