Jump to content

  • Log In with Google      Sign In   
  • Create Account

#Actualslicer4ever

Posted 16 November 2013 - 02:55 PM

Excellent work fuzzy, had to make a slight modification for msvc(cmath does not include round):
 
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <vector>
#include <cmath>
#include <stdint.h>
#include <iostream>
#include <cstring>
#include <sstream>

typedef unsigned int uint; // laziness
typedef unsigned char uchar; // more

#ifndef round
double round(double d){
	return floor(d+0.5);
}

#endif

union RGBA
{
	struct Channel
	{
		uint8_t red;
		uint8_t green;
		uint8_t blue;
		uint8_t alpha;
	};

	uint32_t rgba;
	Channel channel;
};

struct ImageData32
{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[32 * 32 * 4 + 1];
};

struct ImageData64{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[64*64*4+1];
};

struct Ghost
{
	sf::Vector2f position;
	sf::Vector2f oldPosition;
	sf::Vector2f forces;
	float scaleRate;
	float radius;
	float invmass;
	int m_GoodAmnt;
	sf::Sprite sprite;
};

struct ShadowGhost
{
	sf::Sprite sprite;
	float fadeDuration;
	float maxVisibility;
	float fadeState;
};

struct People{
	sf::Vector2f position;
	float radius;
	sf::Sprite sprite;
	unsigned char m_Flag;
};

struct Background
{
	sf::Color baseColor;
	sf::Image buffer;
	sf::Texture texture;
	float pulseState;

	std::vector<ShadowGhost> shadowGhosts;
};

// Simple "self-sufficient" particles
struct Particle
{
	sf::Vector2f position, velocity;
	float friction;
	float rotation, omega;
	sf::Color color;
	sf::Color endColor;
	uint lifetime;
	uint energy;
};

extern const uchar particleData[];
extern const ImageData32 imageData;
extern const ImageData64 Person_A;
extern const unsigned char InconcolataFont[58464];

#define PLAYER_GHOST 0
#define GHOST_GOOD 1
#define CONVERSION_DISTANCE 80.0f
#define CONVERSION_LARGE_DISTANCE 50.0f
#define GOOD_MINIMUM 100
#define GOOD_MAXIMUM 255
#define BAD_CONVERSION_RATE 6
#define GOOD_CONVERSION_RATE 2
#define GHOST_RADIUS 16.0f
#define GHOST_GROW_RATE 0.2
#define GHOST_SPAWN_MIN_TICKS 30 //0.5 seconds at 60 fps
#define GHOST_SPAWN_MAX_TICKS 120 //2 seconds at 60 fps
#define GHOST_MAX_SCALE 1.8
#define GHOST_MINIMUM_FOR_GOOD_SCALE 5
#define GHOST_SCALE_RATE 0.01f
#define INITIAL_SCORE 3000
#define GOOD_GHOST_SCORE_VALUE 1
#define BAD_GHOST_SCORE_VALUE 1
#define GAME_FASTER_SPAWN_AFTER_TICKS (45*60) //every 45 seconds(60 ticks per second), ghosts begin spawning slightly faster.

typedef enum {
	GameStateMenu = 0,
	GameStatePlaying,
	GameStateGameOver,
} GameState;

#define STATE_MENU GameStateMenu
#define STATE_PLAYING GameStatePlaying

#define PERSON_RADIUS 32.0f
#define PERSON_FACE_LEFT 1

#define GHOST_BUFFER_BLUR_X     16.0f
#define GHOST_BUFFER_BLUR_Y     16.0f
#define GHOST_BUFFER_FADE       240

#define PI                      3.1415926535897f

static sf::Vector2u mousePosition;
static float ghostGravityWellAttraction = 0;
static std::vector<Particle> *gParticles;    // yay global reference
static uint currentRenderTarget;

#define MASS 2 * 1e-2
#define GHOST_GRAVITY_WELL_DIEOFF_RATE (1.0f / 30.0f)

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const float energyScale, const sf::Color colorMin, const sf::Color colorMax, sf::Color *fadeColor=0);

float randomFloat()
{
	return std::rand()/(float)RAND_MAX; //get out of here swiftcoder!
	return 4.0f;//std::rand() / static_cast<float>(RAND_MAX);
}

inline float randomRange(const float min, const float max) {
	return min + (max-min)*randomFloat();
}

sf::Vector2f randomVector(sf::Vector2u bounds)
{
	return sf::Vector2f(randomFloat() * bounds.x, randomFloat() * bounds.y);
}

//return random vector between min/max....although since randomFloat returns 4, more like min+max*4....
sf::Vector2f randomVector(sf::Vector2f min, sf::Vector2f max){
	//sf::Vector2f Vec = min+(max-min);
	//return sf::Vector2f(Vec.x*randomFloat(), Vec.y*randomFloat());
	sf::Vector2f diff = max-min;
	return min + sf::Vector2f(diff.x*randomFloat(), diff.y*randomFloat());
}

sf::Color fadeColors(const sf::Color &start, const sf::Color &end, const float amount) {
	sf::Color color;
	color.r = start.r + amount*int(end.r - start.r);
	color.g = start.g + amount*int(end.g - start.g);
	color.b = start.b + amount*int(end.b - start.b);
	color.a = start.a + amount*int(end.a - start.a);
	return color;
}

//Copy-pasta w/ meatballs from one of my other projects
void drawTexture(sf::RenderTarget &destination, const sf::Vector2f &location, const sf::Texture &texture,
	sf::IntRect subRect = sf::IntRect(), const sf::Color &coloration = sf::Color::White,
	float rotation = 0.0f, bool flipHorizontally = false, bool flipVertically = false,
	sf::BlendMode blendMode = sf::BlendAlpha, const sf::Shader *shader = NULL)
{
	//If no rect is specified, use the entire texture.
	if(subRect.width == 0 || subRect.height == 0)
	{
		subRect.top = 0;
		subRect.left = 0;
		subRect.width = texture.getSize().x;
		subRect.height = texture.getSize().y;
	}

	//Set the position in space.
	sf::Transform translation;
	translation.translate(location);

	//Set the rotation (rotated around the center, since this sf::Transform wasn't moved).
	sf::Transform rotationTransform;
	rotationTransform.rotate(rotation);

	//Setup the render state.
	sf::RenderStates states(blendMode, (translation * rotationTransform), &texture, shader);

	//Setup the vertices and their attributes.
	sf::Vertex vertices[4];

	//The transparency:
	vertices[0].color = coloration;
	vertices[1].color = coloration;
	vertices[2].color = coloration;
	vertices[3].color = coloration;

	//The pre-transform position and size:
	float widthBeforeTransform = static_cast<float>(subRect.width);
	float heightBeforeTransform = static_cast<float>(subRect.height);
	vertices[0].position = sf::Vector2f(0, 0);
	vertices[1].position = sf::Vector2f(0, heightBeforeTransform);
	vertices[2].position = sf::Vector2f(widthBeforeTransform, heightBeforeTransform);
	vertices[3].position = sf::Vector2f(widthBeforeTransform, 0);

	//Calculate the texture coordinates:
	float left   = static_cast<float>(subRect.left);
	float right  = left + subRect.width;
	float top    = static_cast<float>(subRect.top);
	float bottom = top + subRect.height;

	//If we're mirroring, swap the texture coordinates vertically and/or horizontally.
	if(flipVertically)        std::swap(top, bottom);
	if(flipHorizontally)    std::swap(left, right);

	//Set the texture coordinates:
	vertices[0].texCoords = sf::Vector2f(left, top);
	vertices[1].texCoords = sf::Vector2f(left, bottom);
	vertices[2].texCoords = sf::Vector2f(right, bottom);
	vertices[3].texCoords = sf::Vector2f(right, top);

	//Use the sf::RenderTarget to draw the vertices using the sf::RenderStates we set up.
	destination.draw(vertices, 4, sf::Quads, states);
}


//returns good ghost counter.
unsigned int ghostAdvance(std::vector <Ghost> &vec, std::vector<Ghost *> &good, sf::Vector2u screenSize){
	unsigned int GoodGhosts = 0;
	// gravity well test (it is a feature)
	//now it's gameplay!
	for (size_t i = 0; i < vec.size(); ++i)
	{
		goto LABELE;
		if (i == PLAYER_GHOST) continue; // if you remove this a ghost will die
LABELE:
		if(vec[i].m_GoodAmnt<GOOD_MINIMUM) continue;
		Ghost *p = &(vec[i]);

		sf::Vector2f r = p->position - sf::Vector2f(mousePosition.x, mousePosition.y);
		r.x = r.x / screenSize.x;
		r.y = r.y / screenSize.y;

		double len2 = pow(r.x, 2) + pow(r.y, 2);
		r = sf::Vector2f(r.x / sqrt(len2), r.y / sqrt(len2));

		const float MIN = 0.02;
		if (len2 < MIN) len2 = MIN;

		double ax = r.x * (+1) * MASS / len2; // physics
		double ay = r.y * (+1) * MASS / len2;

		p->forces = sf::Vector2f(ax, ay) * ghostGravityWellAttraction;
		GoodGhosts++;
		good.push_back(p);
	}

	for(size_t i=0;i<vec.size();i++){
		Ghost *p = &(vec[i]);
		//Verlet integration
		sf::Vector2f oldPos = p->position;
		p->position += p->position - (p->oldPosition + (p->forces * 0.5f));
		p->oldPosition = oldPos;

		//Wall collision detection
		double overY = 0;
		if(p->position.y > screenSize.y-p->radius)
			overY = (screenSize.y-p->radius) - p->position.y;
		if(p->position.y < p->radius)
			overY = (p->radius) - p->position.y;
		if(p->position.x < p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = p->radius;
		}
		if(p->position.x > screenSize.x-p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = screenSize.x-p->radius;
		}

		//Friction with floor
		if(overY != 0){
			p->oldPosition.y = p->position.y;
			p->position.y += overY;
			double xVel = p->position.x - p->oldPosition.x;
			if(xVel != 0)
				p->position.x -= (xVel * 0.1);
		}
	}
	//Ghost-Ghost collision detection
	for(size_t i=0;i<vec.size();i++){
		//fixed j to i+1
		for(size_t j=i+1;j<vec.size();j++){
			Ghost *pi = &(vec[i]);
			Ghost *pj = &(vec[j]);

			float dx = pj->position.x-pi->position.x;
			float dy = pj->position.y-pi->position.y;
			float a = dx*dx+dy*dy;
			float l = (pi->radius + pj->radius);
			//do conversion if within distance.
			if(a<=CONVERSION_DISTANCE*CONVERSION_DISTANCE){
				int BadRate = GoodGhosts>3?BAD_CONVERSION_RATE:0;
				if((vec[i].m_GoodAmnt>=GOOD_MINIMUM && vec[j].m_GoodAmnt<GOOD_MINIMUM)){ //i is good, j is bad
					vec[i].m_GoodAmnt -= BadRate * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM && vec[j].m_GoodAmnt>=GOOD_MINIMUM){
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BadRate * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM){ //both i and j are bad.
					vec[i].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else{ //both are good.
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}
				vec[i].m_GoodAmnt = vec[i].m_GoodAmnt<0?0:vec[i].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[i].m_GoodAmnt;
				vec[j].m_GoodAmnt = vec[j].m_GoodAmnt<0?0:vec[j].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[j].m_GoodAmnt;
			}
			if(a <= l*l ){
				bool massfix=false;
				if(pi->invmass == 0 && pj->invmass == 0){
					massfix = true;
					pi->invmass = pj->invmass = 1;
				}
				if(a==0) continue;
				float dist = sqrt(a);
				float difference = (dist - l) / (dist*(pi->invmass+pj->invmass));

				pi->position.x += pi->invmass * dx * difference * 0.5;
				pi->position.y += pi->invmass * dy * difference * 0.5;
				pj->position.x -= pj->invmass * dx * difference * 0.5;
				pj->position.y -= pj->invmass * dy * difference * 0.5;

				if(massfix){
					pi->invmass = pj->invmass = 0;
				}
				goto LABELF;
				if(i==PLAYER_GHOST){
					//ghost hit player!
					vec.erase(vec.begin()+j--);
					continue;
				}
LABELF:;

				sf::Vector2f ppos = pi->position + sf::Vector2f(dx*difference*0.5f, dy*difference*0.5f);
				sf::Color fadeColor(255, 200, 10, 0);
				addParticles(gParticles, 4, ppos, ppos, pi->position-pi->oldPosition, pj->position-pj->oldPosition, 0.998f, 60, 1.0f, pi->sprite.getColor(), pj->sprite.getColor(), &fadeColor);
			}
		}

		// convert to bigger "good" ghost
		for(size_t i=0;i<vec.size();i++){
			if(vec[i].scaleRate>0.001f){
				float s = vec[i].scaleRate>GHOST_SCALE_RATE?GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
			}else if(vec[i].scaleRate<-0.001f){
				float s = vec[i].scaleRate<-GHOST_SCALE_RATE?-GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
				if(vec[i].scaleRate>=-0.001f){ //it is now a dead ghost.
					vec.erase(vec.begin()+i--);
				}
			}else{
				for(size_t j=i+1;j<vec.size();j++){
					//fixed double testing i/j
					//now bad ghosts can get bigger as well!
					if(vec[j].scaleRate>=0.0001f || vec[j].scaleRate<=-0.0001f) continue; //only scale up when not scaling itself.
					if ((vec[i].m_GoodAmnt == GOOD_MAXIMUM && vec[j].m_GoodAmnt == GOOD_MAXIMUM && GoodGhosts > GHOST_MINIMUM_FOR_GOOD_SCALE) || (vec[i].m_GoodAmnt==0 && vec[j].m_GoodAmnt==0))
					{
						if (vec[i].sprite.getScale().x >= GHOST_MAX_SCALE) break;

						float distanceBetweenX = vec[i].position.x - vec[j].position.x;
						float distanceBetweenY = vec[i].position.y - vec[j].position.y;

						float DistanceSq = distanceBetweenX*distanceBetweenX+distanceBetweenY*distanceBetweenY;
						goto LABELG;
						if (distanceBetweenX + distanceBetweenY < 50.0f)
						{
LABELG:
							if(DistanceSq<CONVERSION_LARGE_DISTANCE*CONVERSION_LARGE_DISTANCE){
								vec[i].scaleRate = (vec[j].sprite.getScale().x-1.0f)+GHOST_GROW_RATE;
								vec[j].scaleRate = -vec[j].sprite.getScale().x;
								goto LABELH;
								vec[i].sprite.setScale(vec[i].sprite.getScale().x + (vec[j].sprite.getScale().x - 1.0f) + 0.5f, vec[i].sprite.getScale().y + (vec[j].sprite.getScale().y - 1.0f) + 0.5f);
								vec[i].radius += 0.5f;
								vec[j] = vec[vec.size() - 1];
								vec.pop_back();
								GoodGhosts--;
LABELH:
								break;
							}
						}
					}
				}
			}
		}

	}
	return GoodGhosts;
}

int ghostAdd(std::vector <Ghost> &vec, sf::Vector2f position, sf::Vector2f velocity, sf::Texture &textureBall, int GoodAmnt){
	Ghost gh;
	gh.position = position;
	gh.oldPosition = position-velocity;
	gh.forces = sf::Vector2f(0, -0.001);
	gh.invmass = 1;
	gh.radius = GHOST_RADIUS;
	gh.scaleRate = 0.0f;
	gh.m_GoodAmnt = GoodAmnt;
	gh.sprite.setTexture(textureBall);
	gh.sprite.setColor(sf::Color((int)position.x%256,(int)position.y%256,rand()%256,200));

	// add some particles
	sf::Color fadeColor = sf::Color::White;
	fadeColor.a = 0;
	addParticles(gParticles, 10, position, position, sf::Vector2f(-2.0f, -2.0f), sf::Vector2f(2.0f, 2.0f), 0.998f, 100, 1.0f, gh.sprite.getColor(), sf::Color::White, &fadeColor);


	vec.push_back(gh);
	return vec.size()-1; //return index of ghost.
}

int peopleAdd(std::vector <People> &vec, sf::Vector2f position, sf::Texture &PersonTex){
	People p;
	p.position = position;
	p.sprite.setTexture(PersonTex);
	p.radius = PERSON_RADIUS;
	p.m_Flag = rand()%100<50?PERSON_FACE_LEFT:0;
	p.sprite.setColor(sf::Color(255,255,255,100));
	vec.push_back(p);
	return vec.size()-1; //return index of person.
}

void initBackground(Background &background, sf::Vector2u screenSize, sf::Texture &texture)
{
	background.baseColor = sf::Color(180, 200, 215); // 85, 128, 160); //
	background.pulseState = 0.0f;

	background.buffer.create(screenSize.x, screenSize.y, background.baseColor);
	background.texture.create(screenSize.x, screenSize.y);

	int numShadowGhosts = 7;

	for(int i = 0; i < numShadowGhosts; ++i)
	{
		ShadowGhost shadowGhost;
		shadowGhost.fadeDuration = (randomFloat() * 25.0f) + 10.0f;
		shadowGhost.maxVisibility = (randomFloat() * 0.35f) + 0.1f;
		shadowGhost.fadeState = (randomFloat() * shadowGhost.fadeDuration);
		shadowGhost.sprite.setTexture(texture);
		shadowGhost.sprite.setPosition(randomVector(screenSize));

		background.shadowGhosts.push_back(shadowGhost);
	}
}

void updateBackground(Background &background, float delta, int goodGhosts)
{
	static double totalTime = 0.0f;
	totalTime += delta;

	sf::Color bgColor = background.baseColor;

	float durationOfPulse = 10.0f;
	float halfDuration = (durationOfPulse * 0.5f);

	float state = fmod(totalTime, (double)durationOfPulse);

	if(state > halfDuration) background.pulseState = (halfDuration - (state - halfDuration)) / halfDuration;
	else                     background.pulseState = (state / halfDuration);

	if(goodGhosts > 2) goodGhosts -= 2;

	float redVariance = 20.0f + (7.0f * std::min(goodGhosts, 5));
	float variance = 30.0f;

	//Darken the room slowly and back.
	bgColor.r -= uint8_t(std::min(float(bgColor.r), redVariance) * background.pulseState);
	bgColor.g -= uint8_t(std::min(float(bgColor.g), variance) * background.pulseState);
	bgColor.b -= uint8_t(std::min(float(bgColor.b), variance) * background.pulseState);

	for(int y = 0; y < background.buffer.getSize().y; ++y)
	{
		for(int x = 0; x < background.buffer.getSize().x; ++x)
		{
			background.buffer.setPixel(x, y, bgColor);
		}
	}

	background.texture.update(background.buffer);
}

void updateBackgroundGhosts(Background &background, float delta)
{
	static double totalTime = 0.0f;
	totalTime += delta;

	sf::Vector2f movementAmount(100.0f * delta, 100.0f * delta);

	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];

		float state = fmod(totalTime, (double)shadowGhost.fadeDuration);
		float halfDuration = (shadowGhost.fadeDuration * 0.5f);

		if(state > halfDuration) shadowGhost.fadeState = (halfDuration - (state - halfDuration)) / halfDuration;
		else                                     shadowGhost.fadeState = (state / halfDuration);


		//shadowGhost.sprite.move(movementAmount);
		shadowGhost.sprite.setScale(0.5f + shadowGhost.fadeState, 0.5f + shadowGhost.fadeState);

		//Wave
		sf::Vector2f newPos(0,0);
		float randomNumber =  randomFloat()*30 + 10;

		newPos.y = -sin(totalTime * 3) * delta * randomNumber;
		newPos.x =  sin(totalTime * 3) * delta * randomNumber;

		shadowGhost.sprite.move(newPos+movementAmount);

		//If out of bounds (towards the lower-right of the screen)...
		if(shadowGhost.sprite.getPosition().x > (background.buffer.getSize().x + 100.0f)
			|| shadowGhost.sprite.getPosition().y > (background.buffer.getSize().y + 100.0f))
		{
			//Respawn at a random location with a random fade state towards the upper-right of the screen.
			shadowGhost.fadeState = (randomFloat() * 1.0f);
			shadowGhost.sprite.setPosition(randomFloat() * float(background.buffer.getSize().x) - 200.0f,
				randomFloat() * float(background.buffer.getSize().y) - 200.0f);
		}
	}
}

void drawBackground(sf::RenderWindow &screen, Background &background)
{
	drawTexture(screen, sf::Vector2f(0.0f, 0.0f), background.texture);
}

void drawBackgroundGhosts(sf::RenderTarget &screen, Background &background)
{
	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];
		shadowGhost.sprite.setColor(sf::Color(0, int(32.0f + (64.0f * shadowGhost.maxVisibility)),
			int(96.0f + (64.0f * shadowGhost.maxVisibility)), int(shadowGhost.fadeState * shadowGhost.maxVisibility * 255.0f)));
		screen.draw(shadowGhost.sprite);
	}
}

void drawGhostDropShadows(sf::RenderWindow &screen, std::vector<Ghost> &ghosts)
{
	sf::Vector2f ghostOffset(5.0f, 7.0f);//5.0f,5.0f);

	for(size_t i = 0; i < ghosts.size(); ++i)
	{
		double rad = ghosts[i].radius;
		ghosts[i].sprite.setPosition(ghosts[i].position - sf::Vector2f(rad, rad) + ghostOffset);
		ghosts[i].sprite.setColor(sf::Color(85, 128, 160, ghosts[i].m_GoodAmnt * 4 % 256));
		screen.draw(ghosts[i].sprite);
	}
}

void updateParticles(std::vector<Particle> *particles) {

	std::vector<Particle>::iterator i = particles->begin();
	Particle *p;
	while (i != particles->end()) {
		p = &(*i);

		if (p->lifetime == 0) {
			i = particles->erase(i);
			continue;
		}

		// euler, no acceleration for now
		p->position += p->velocity;
		p->velocity *= p->friction;
		p->rotation += p->omega;

		p->lifetime--;

		++i;
	}

}

void drawParticles(sf::RenderTarget *screen, std::vector<Particle> &particles, const sf::Texture &texture) {
	for (size_t i=0;i<particles.size();++i) {
		sf::Color color;
		if (particles[i].color != particles[i].endColor)
			color = fadeColors(particles[i].color, particles[i].endColor, 1.0f - std::max(0.0f, std::min(particles[i].lifetime / (float)particles[i].energy, 1.0f)));
		else
			color = particles[i].color;

		// this could be faster
		drawTexture(*screen, particles[i].position, texture, sf::IntRect(), color, particles[i].rotation);

	}
}

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const float energyScale, const sf::Color colorMin, const sf::Color colorMax, sf::Color *fadeColor) {
	sf::Vector2f pdiff = posMax - posMin;
	sf::Vector2f vdiff = velMax - velMin;

	for (int i=0;i<count;++i) {
		Particle p;
		p.position = randomVector(posMin, posMax);
		p.velocity = randomVector(velMin, velMax);
		p.friction = friction;
		p.rotation = randomFloat()*PI*2.0f;
		p.omega = randomRange(-4.0f*PI, 4.0f*PI);

		// life time is in ticks
		p.lifetime = lifetime;
		p.energy = lifetime*energyScale;

		float r = randomFloat();
		p.color = colorMin;
		p.color.r += r*(colorMax.r - colorMin.r);
		p.color.g += r*(colorMax.g - colorMin.g);
		p.color.b += r*(colorMax.b - colorMin.b);
		p.color.a += r*(colorMax.a - colorMin.a);

		if (fadeColor != 0)
			p.endColor = *fadeColor;
		else
			p.endColor = p.color;

		particles->push_back(p);
	}
}

void pingPongGhostBuffers(sf::RenderTexture *buffers, const sf::Color &clearColor) {
	int lastRenderTarget = currentRenderTarget;
	currentRenderTarget = !currentRenderTarget;
	buffers[currentRenderTarget].clear(clearColor);
	buffers[lastRenderTarget].display();
	// "ghost" the other buffer onto the fresh one
	drawTexture(buffers[currentRenderTarget], sf::Vector2f(0.0f, 0.0f), buffers[lastRenderTarget].getTexture(), sf::IntRect(), sf::Color(255, 255, 255, GHOST_BUFFER_FADE), 0.0f, false, false, sf::BlendNone);

}

// forward declaration
void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
	sf::Texture &texture, sf::Texture &People_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles, sf::Font &GameFont, sf::RenderTexture *ghostBuffers);

int main()
{
	std::srand(static_cast<unsigned>(std::time(0)));
	sf::RenderWindow screen(sf::VideoMode(800, 600, 32), "Ghost Horror Code");
	screen.setFramerateLimit(60);

	//Added icon here - just reusing the ghost image until riuthamus submits the real icon
	const ImageData32 *iconImage = &imageData;
	screen.setIcon(iconImage->width, iconImage->height, iconImage->pixel_data);

	sf::Image image, imageBall;
	image.create(imageData.width, imageData.height, imageData.pixel_data);
	image.createMaskFromColor(sf::Color::Black, 0);

	sf::Image PersonImage;
	PersonImage.create(Person_A.width, Person_A.height, Person_A.pixel_data);
	PersonImage.createMaskFromColor(sf::Color::Black, 0);

	sf::Texture texture;
	sf::Texture PersonTex;
	sf::Texture particleTex;

	texture.loadFromImage(image);
	texture.setSmooth(true);
	PersonTex.loadFromImage(PersonImage);
	PersonTex.setSmooth(true);

	sf::Sprite sprite;
	sf::Vector2f position = randomVector(screen.getSize() - image.getSize());
	sf::Vector2f Velocity = randomVector(sf::Vector2f(-1.0f, -1.0f), sf::Vector2f(1.0f, 1.0f));

	//Add out game font!
	sf::Font m_GameFont;
	m_GameFont.loadFromMemory(InconcolataFont, sizeof(InconcolataFont));

	Background background;
	initBackground(background, screen.getSize(), texture);

	uchar pdata[64];
	memset(pdata, 255, 64); // not quite what I expected, but it's good for now lol
	sf::Image pimage;
	// Since it should be 4 channels, proper image added.
	pimage.create(8, 8, particleData);
	particleTex.loadFromImage(pimage);

	currentRenderTarget = 1;
	sf::RenderTexture ghostBuffers[2];
	for (int i=0;i<2;++i) // yep just did a for loop for 2! 8]
	{
		ghostBuffers[i].create(screen.getSize().x, screen.getSize().y);
		ghostBuffers[i].clear(sf::Color(255, 255, 255, 0));
	}


	goto LABELA;
	sprite.setTexture(texture);
	sprite.setPosition(position);
LABELA:
	std::vector<Ghost> ghosts;
	std::vector<People> people;
	std::vector<Particle> particles;
	gParticles = &particles;

	goto LABELK;
	//spawn initial 3 ghosts.
	for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
	//spawn a dude!
	peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), PersonTex);
LABELK:
	loop(screen, background, position, Velocity, image, sprite, texture, PersonTex, particleTex, ghosts, people, &particles, m_GameFont, ghostBuffers);
}

void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
	sf::Texture &texture, sf::Texture &Person_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles, sf::Font &GameFont, sf::RenderTexture *ghostBuffers) {

		//don't want to thrash the stack with the tail recursion
		static sf::Clock clock;
		static unsigned int SpawnTick = GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
		static int HighScore = 0;
		static int ActiveScore = 0;
		static int LastHighScore = 0;
		static int GameTicks = 0;
		static int GameState = STATE_MENU;
		static std::vector<Ghost *> allGoodGhosts;
		static sf::Color gameOverTextColors[4] = {sf::Color(255, 0, 0), sf::Color(0, 255, 0), sf::Color(0, 0, 255), sf::Color(255, 200, 0)};
		static int gameOverColorIndex[2] = {0,1};
		static float gameOverColorFade = 0.0f;
		bool running = true;
		mousePosition = sf::Vector2u(screen.getSize().x/2, screen.getSize().y/2);

		//Game Text
		// Replacement for below..
		static sf::Text ScoreText, PlayText, gameOverText;
		ScoreText.setFont(GameFont);
		PlayText.setFont(GameFont);
		gameOverText.setFont(GameFont);
		PlayText.setString("Play");
		gameOverText.setString("\tGame Over!\nClick to play again");
		// Not really sure why these lines crash on me, but the above works fine and achieves the same thing, meh.
		//static sf::Text ScoreText("", GameFont);
		//static sf::Text PlayText("Play", GameFont);
		//Position PlayText
		sf::Rect<float> PlayBounds = PlayText.getLocalBounds();
		PlayText.setPosition(screen.getSize().x*0.5f-PlayBounds.width*0.5f, screen.getSize().y*0.5f-PlayBounds.height*0.5f);
		gameOverText.setPosition(screen.getSize().x*0.5f-gameOverText.getLocalBounds().width*0.5f, screen.getSize().y*0.5f-gameOverText.getLocalBounds().height*0.5f);
		static std::ostringstream ScoreString;
		ScoreText.setString(ScoreString.str());
		while(running){
			float deltaTime = clock.getElapsedTime().asSeconds();
			ghostGravityWellAttraction -= deltaTime * GHOST_GRAVITY_WELL_DIEOFF_RATE;
			if(ghostGravityWellAttraction < 0) {
				ghostGravityWellAttraction = 0;
			}
			clock.restart();

			sf::Event event;
			while (screen.pollEvent(event))
			{
				if (event.type == sf::Event::Closed)
				{
					running = false;
				}else
					if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
					{
						running = false;
					}else
						if (event.type == sf::Event::MouseMoved)
						{
							mousePosition = sf::Vector2u(event.mouseMove.x, event.mouseMove.y);
							ghostGravityWellAttraction = 1;
						}else
							if(event.type == sf::Event::MouseButtonPressed){
								if(GameState==STATE_MENU && PlayText.getGlobalBounds().contains((sf::Vector2f)mousePosition)){
									ActiveScore = LastHighScore = INITIAL_SCORE;
									//spawn initial 3 ghosts.
									for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
									//spawn a dude!
									peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), Person_ATex);
									GameState=STATE_PLAYING;
								}
								if (GameState == GameStateGameOver) {
									ActiveScore = INITIAL_SCORE;
									//spawn initial 3 ghosts.
									for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
									//spawn a dude!
									peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), Person_ATex);
									GameState=STATE_PLAYING;

								}
							}
			}
			goto LABELB;
			position+=Velocity;
			if(position.x<0.0f){
				position.x = 0.0f;
				Velocity.x = -Velocity.x;
			}else if(position.x>=(float)(screen.getSize().x-image.getSize().x)){
				position.x = (float)(screen.getSize().x-image.getSize().x);
				Velocity.x = -Velocity.x;
			}
			if(position.y<0.0f){
				position.y = 0.0f;
				Velocity.y = -Velocity.y;
			}else if(position.y>=(float)(screen.getSize().y-image.getSize().y)){
				position.y = (float)(screen.getSize().y-image.getSize().y);
				Velocity.y = -Velocity.y;
			}
			sprite.setPosition(position);  //Good bye old crap.
LABELB:
			allGoodGhosts.clear();
			int goodGhosts = ghostAdvance(ghosts, allGoodGhosts, screen.getSize());
			updateBackground(background, deltaTime, goodGhosts);
			updateBackgroundGhosts(background, deltaTime);
			updateParticles(particles);

			screen.clear();
			drawBackground(screen, background);

			// Ping pong between ghost buffers
			pingPongGhostBuffers(ghostBuffers, sf::Color(255, 255, 255, 0));

			drawBackgroundGhosts(ghostBuffers[currentRenderTarget], background);
			//Let's draw particles here!
			goto LABELW;
LABELX:

			ghostBuffers[currentRenderTarget].display();
			drawTexture(screen, sf::Vector2f(0.0f, 0.0f), ghostBuffers[currentRenderTarget].getTexture());

			drawGhostDropShadows(screen, ghosts);


			goto LABELC;
			screen.draw(sprite);
LABELC:
			//draw people!
			for(size_t i=0;i<people.size();i++){
				float rad = people[i].radius;
				people[i].sprite.setPosition(people[i].position-sf::Vector2f(rad, rad));
				people[i].sprite.setScale((people[i].m_Flag&PERSON_FACE_LEFT)?-1.0f:1.0f, 1.0f);
				screen.draw(people[i].sprite);
			}

			//int GoodIncrement = 0;
			//int BadIncrement = 0;
			for(size_t i=0;i<ghosts.size();i++){
				double rad = ghosts[i].radius;
				ghosts[i].sprite.setPosition(ghosts[i].position-sf::Vector2f(rad, rad));
				ghosts[i].sprite.setColor(sf::Color(GOOD_MAXIMUM-ghosts[i].m_GoodAmnt, 0, ghosts[i].m_GoodAmnt, 25+ghosts[i].m_GoodAmnt * 4 % 231 ));
				screen.draw(ghosts[i].sprite);

				//Do score calculations!
				if(GameState==STATE_PLAYING) ActiveScore+=(ghosts[i].m_GoodAmnt>=GOOD_MINIMUM?GOOD_GHOST_SCORE_VALUE:-BAD_GHOST_SCORE_VALUE)*(ghosts[i].sprite.getScale().x+(ghosts[i].sprite.getScale().x-1.0f)*2.0f);
				else ghosts[i].scaleRate=-ghosts[i].sprite.getScale().x; //destroy all ghosts when in the menu
			}
			HighScore = ActiveScore>HighScore?ActiveScore:HighScore;
			LastHighScore = ActiveScore>LastHighScore?ActiveScore:LastHighScore;
			goto GAMEOVERCHECK;
			if(ActiveScore<=0) GameState=STATE_MENU;
GAMEOVERCHECK:
			if (ActiveScore <= 0) {
				for (int i=0;i<goodGhosts;++i) {
					allGoodGhosts[i]->m_GoodAmnt -= 2.0f*BAD_CONVERSION_RATE;
				}
				ActiveScore = 0;
			}
			if (GameState == GameStatePlaying && goodGhosts <= 0) GameState = GameStateGameOver;


			ScoreString.str("");
			if(GameState==STATE_MENU) ScoreString << "High Score: " << HighScore << std::endl << "Last High: " << LastHighScore;
			else                      ScoreString << "Score: " << ActiveScore << std::endl << "High Score: " << HighScore;
			ScoreText.setString(ScoreString.str());
			goto LABELG;
			if(rand()%50 == 0 || rand() % 60 >= 57) //decreased rate of spawning.
LABELG:
			if(GameState==STATE_MENU){
				if(PlayText.getGlobalBounds().contains((sf::Vector2f)mousePosition)) PlayText.setColor(sf::Color(255, 0, 0));
				else PlayText.setColor(sf::Color(255,255,255));
				screen.draw(PlayText);

			} else if (GameState == GameStateGameOver) {
				gameOverColorFade += 0.02f;
				if (gameOverColorFade >= 1.0f) {
					gameOverColorIndex[0] = gameOverColorIndex[1];
					int count;
					
					while ((gameOverColorIndex[1] = round(randomFloat()*3)) == gameOverColorIndex[0] && count++ < 10);
					gameOverColorFade = 0.0f;
				}
				sf::Color c = fadeColors(gameOverTextColors[gameOverColorIndex[0]], gameOverTextColors[gameOverColorIndex[1]], gameOverColorFade);
				gameOverText.setColor(c);
				screen.draw(gameOverText);

			}else{
				if(SpawnTick==0){
					ghostAdd(ghosts, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)screen.getSize()),
						sf::Vector2f(rand()%20-10, rand()%20-10), texture, 0);
					SpawnTick=GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
				}else{
					//The longer the game goes on, the faster we spawn.
					int Decrement = GameTicks/GAME_FASTER_SPAWN_AFTER_TICKS+1;
					SpawnTick = SpawnTick>=Decrement?SpawnTick-Decrement:0;
				}
			}
			GameTicks++;
			goto LABELY;
LABELW:
			drawParticles(&ghostBuffers[currentRenderTarget], *particles, particleTex);
			goto LABELX;
LABELY:
			screen.draw(ScoreText);

			screen.display();
		}

		if (running) {
			loop(screen, background, position, Velocity, image, sprite, texture, particleTex, Person_ATex, ghosts, people, particles, GameFont, ghostBuffers);
		}
}

#error "Be sure to add resources here!"
see attachment for full file.

also, video:


#2slicer4ever

Posted 16 November 2013 - 02:48 PM

Excellent work fuzzy, had to make a slight modification for msvc(cmath does not include round):
 
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <vector>
#include <cmath>
#include <stdint.h>
#include <iostream>
#include <cstring>
#include <sstream>

typedef unsigned int uint; // laziness
typedef unsigned char uchar; // more

#ifndef round
double round(double d){
	return floor(d+0.5);
}

#endif

union RGBA
{
	struct Channel
	{
		uint8_t red;
		uint8_t green;
		uint8_t blue;
		uint8_t alpha;
	};

	uint32_t rgba;
	Channel channel;
};

struct ImageData32
{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[32 * 32 * 4 + 1];
};

struct ImageData64{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[64*64*4+1];
};

struct Ghost
{
	sf::Vector2f position;
	sf::Vector2f oldPosition;
	sf::Vector2f forces;
	float scaleRate;
	float radius;
	float invmass;
	int m_GoodAmnt;
	sf::Sprite sprite;
};

struct ShadowGhost
{
	sf::Sprite sprite;
	float fadeDuration;
	float maxVisibility;
	float fadeState;
};

struct People{
	sf::Vector2f position;
	float radius;
	sf::Sprite sprite;
	unsigned char m_Flag;
};

struct Background
{
	sf::Color baseColor;
	sf::Image buffer;
	sf::Texture texture;
	float pulseState;

	std::vector<ShadowGhost> shadowGhosts;
};

// Simple "self-sufficient" particles
struct Particle
{
	sf::Vector2f position, velocity;
	float friction;
	float rotation, omega;
	sf::Color color;
	sf::Color endColor;
	uint lifetime;
	uint energy;
};

extern const uchar particleData[];
extern const ImageData32 imageData;
extern const ImageData64 Person_A;
extern const unsigned char InconcolataFont[58464];

#define PLAYER_GHOST 0
#define GHOST_GOOD 1
#define CONVERSION_DISTANCE 80.0f
#define CONVERSION_LARGE_DISTANCE 50.0f
#define GOOD_MINIMUM 100
#define GOOD_MAXIMUM 255
#define BAD_CONVERSION_RATE 6
#define GOOD_CONVERSION_RATE 2
#define GHOST_RADIUS 16.0f
#define GHOST_GROW_RATE 0.2
#define GHOST_SPAWN_MIN_TICKS 30 //0.5 seconds at 60 fps
#define GHOST_SPAWN_MAX_TICKS 120 //2 seconds at 60 fps
#define GHOST_MAX_SCALE 1.8
#define GHOST_MINIMUM_FOR_GOOD_SCALE 5
#define GHOST_SCALE_RATE 0.01f
#define INITIAL_SCORE 3000
#define GOOD_GHOST_SCORE_VALUE 1
#define BAD_GHOST_SCORE_VALUE 1
#define GAME_FASTER_SPAWN_AFTER_TICKS (45*60) //every 45 seconds(60 ticks per second), ghosts begin spawning slightly faster.

typedef enum {
	GameStateMenu = 0,
	GameStatePlaying,
	GameStateGameOver,
} GameState;

#define STATE_MENU GameStateMenu
#define STATE_PLAYING GameStatePlaying

#define PERSON_RADIUS 32.0f
#define PERSON_FACE_LEFT 1

#define GHOST_BUFFER_BLUR_X     16.0f
#define GHOST_BUFFER_BLUR_Y     16.0f
#define GHOST_BUFFER_FADE       240

#define PI                      3.1415926535897f

static sf::Vector2u mousePosition;
static float ghostGravityWellAttraction = 0;
static std::vector<Particle> *gParticles;    // yay global reference
static uint currentRenderTarget;

#define MASS 2 * 1e-2
#define GHOST_GRAVITY_WELL_DIEOFF_RATE (1.0f / 30.0f)

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const float energyScale, const sf::Color colorMin, const sf::Color colorMax, sf::Color *fadeColor=0);

float randomFloat()
{
	return std::rand()/(float)RAND_MAX; //get out of here swiftcoder!
	return 4.0f;//std::rand() / static_cast<float>(RAND_MAX);
}

inline float randomRange(const float min, const float max) {
	return min + (max-min)*randomFloat();
}

sf::Vector2f randomVector(sf::Vector2u bounds)
{
	return sf::Vector2f(randomFloat() * bounds.x, randomFloat() * bounds.y);
}

//return random vector between min/max....although since randomFloat returns 4, more like min+max*4....
sf::Vector2f randomVector(sf::Vector2f min, sf::Vector2f max){
	//sf::Vector2f Vec = min+(max-min);
	//return sf::Vector2f(Vec.x*randomFloat(), Vec.y*randomFloat());
	sf::Vector2f diff = max-min;
	return min + sf::Vector2f(diff.x*randomFloat(), diff.y*randomFloat());
}

sf::Color fadeColors(const sf::Color &start, const sf::Color &end, const float amount) {
	sf::Color color;
	color.r = start.r + amount*int(end.r - start.r);
	color.g = start.g + amount*int(end.g - start.g);
	color.b = start.b + amount*int(end.b - start.b);
	color.a = start.a + amount*int(end.a - start.a);
	return color;
}

//Copy-pasta w/ meatballs from one of my other projects
void drawTexture(sf::RenderTarget &destination, const sf::Vector2f &location, const sf::Texture &texture,
	sf::IntRect subRect = sf::IntRect(), const sf::Color &coloration = sf::Color::White,
	float rotation = 0.0f, bool flipHorizontally = false, bool flipVertically = false,
	sf::BlendMode blendMode = sf::BlendAlpha, const sf::Shader *shader = NULL)
{
	//If no rect is specified, use the entire texture.
	if(subRect.width == 0 || subRect.height == 0)
	{
		subRect.top = 0;
		subRect.left = 0;
		subRect.width = texture.getSize().x;
		subRect.height = texture.getSize().y;
	}

	//Set the position in space.
	sf::Transform translation;
	translation.translate(location);

	//Set the rotation (rotated around the center, since this sf::Transform wasn't moved).
	sf::Transform rotationTransform;
	rotationTransform.rotate(rotation);

	//Setup the render state.
	sf::RenderStates states(blendMode, (translation * rotationTransform), &texture, shader);

	//Setup the vertices and their attributes.
	sf::Vertex vertices[4];

	//The transparency:
	vertices[0].color = coloration;
	vertices[1].color = coloration;
	vertices[2].color = coloration;
	vertices[3].color = coloration;

	//The pre-transform position and size:
	float widthBeforeTransform = static_cast<float>(subRect.width);
	float heightBeforeTransform = static_cast<float>(subRect.height);
	vertices[0].position = sf::Vector2f(0, 0);
	vertices[1].position = sf::Vector2f(0, heightBeforeTransform);
	vertices[2].position = sf::Vector2f(widthBeforeTransform, heightBeforeTransform);
	vertices[3].position = sf::Vector2f(widthBeforeTransform, 0);

	//Calculate the texture coordinates:
	float left   = static_cast<float>(subRect.left);
	float right  = left + subRect.width;
	float top    = static_cast<float>(subRect.top);
	float bottom = top + subRect.height;

	//If we're mirroring, swap the texture coordinates vertically and/or horizontally.
	if(flipVertically)        std::swap(top, bottom);
	if(flipHorizontally)    std::swap(left, right);

	//Set the texture coordinates:
	vertices[0].texCoords = sf::Vector2f(left, top);
	vertices[1].texCoords = sf::Vector2f(left, bottom);
	vertices[2].texCoords = sf::Vector2f(right, bottom);
	vertices[3].texCoords = sf::Vector2f(right, top);

	//Use the sf::RenderTarget to draw the vertices using the sf::RenderStates we set up.
	destination.draw(vertices, 4, sf::Quads, states);
}


//returns good ghost counter.
unsigned int ghostAdvance(std::vector <Ghost> &vec, std::vector<Ghost *> &good, sf::Vector2u screenSize){
	unsigned int GoodGhosts = 0;
	// gravity well test (it is a feature)
	//now it's gameplay!
	for (size_t i = 0; i < vec.size(); ++i)
	{
		goto LABELE;
		if (i == PLAYER_GHOST) continue; // if you remove this a ghost will die
LABELE:
		if(vec[i].m_GoodAmnt<GOOD_MINIMUM) continue;
		Ghost *p = &(vec[i]);

		sf::Vector2f r = p->position - sf::Vector2f(mousePosition.x, mousePosition.y);
		r.x = r.x / screenSize.x;
		r.y = r.y / screenSize.y;

		double len2 = pow(r.x, 2) + pow(r.y, 2);
		r = sf::Vector2f(r.x / sqrt(len2), r.y / sqrt(len2));

		const float MIN = 0.02;
		if (len2 < MIN) len2 = MIN;

		double ax = r.x * (+1) * MASS / len2; // physics
		double ay = r.y * (+1) * MASS / len2;

		p->forces = sf::Vector2f(ax, ay) * ghostGravityWellAttraction;
		GoodGhosts++;
		good.push_back(p);
	}

	for(size_t i=0;i<vec.size();i++){
		Ghost *p = &(vec[i]);
		//Verlet integration
		sf::Vector2f oldPos = p->position;
		p->position += p->position - (p->oldPosition + (p->forces * 0.5f));
		p->oldPosition = oldPos;

		//Wall collision detection
		double overY = 0;
		if(p->position.y > screenSize.y-p->radius)
			overY = (screenSize.y-p->radius) - p->position.y;
		if(p->position.y < p->radius)
			overY = (p->radius) - p->position.y;
		if(p->position.x < p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = p->radius;
		}
		if(p->position.x > screenSize.x-p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = screenSize.x-p->radius;
		}

		//Friction with floor
		if(overY != 0){
			p->oldPosition.y = p->position.y;
			p->position.y += overY;
			double xVel = p->position.x - p->oldPosition.x;
			if(xVel != 0)
				p->position.x -= (xVel * 0.1);
		}
	}
	//Ghost-Ghost collision detection
	for(size_t i=0;i<vec.size();i++){
		//fixed j to i+1
		for(size_t j=i+1;j<vec.size();j++){
			Ghost *pi = &(vec[i]);
			Ghost *pj = &(vec[j]);

			float dx = pj->position.x-pi->position.x;
			float dy = pj->position.y-pi->position.y;
			float a = dx*dx+dy*dy;
			float l = (pi->radius + pj->radius);
			//do conversion if within distance.
			if(a<=CONVERSION_DISTANCE*CONVERSION_DISTANCE){
				int BadRate = GoodGhosts>3?BAD_CONVERSION_RATE:0;
				if((vec[i].m_GoodAmnt>=GOOD_MINIMUM && vec[j].m_GoodAmnt<GOOD_MINIMUM)){ //i is good, j is bad
					vec[i].m_GoodAmnt -= BadRate * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM && vec[j].m_GoodAmnt>=GOOD_MINIMUM){
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BadRate * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM){ //both i and j are bad.
					vec[i].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else{ //both are good.
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}
				vec[i].m_GoodAmnt = vec[i].m_GoodAmnt<0?0:vec[i].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[i].m_GoodAmnt;
				vec[j].m_GoodAmnt = vec[j].m_GoodAmnt<0?0:vec[j].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[j].m_GoodAmnt;
			}
			if(a <= l*l ){
				bool massfix=false;
				if(pi->invmass == 0 && pj->invmass == 0){
					massfix = true;
					pi->invmass = pj->invmass = 1;
				}
				if(a==0) continue;
				float dist = sqrt(a);
				float difference = (dist - l) / (dist*(pi->invmass+pj->invmass));

				pi->position.x += pi->invmass * dx * difference * 0.5;
				pi->position.y += pi->invmass * dy * difference * 0.5;
				pj->position.x -= pj->invmass * dx * difference * 0.5;
				pj->position.y -= pj->invmass * dy * difference * 0.5;

				if(massfix){
					pi->invmass = pj->invmass = 0;
				}
				goto LABELF;
				if(i==PLAYER_GHOST){
					//ghost hit player!
					vec.erase(vec.begin()+j--);
					continue;
				}
LABELF:;

				sf::Vector2f ppos = pi->position + sf::Vector2f(dx*difference*0.5f, dy*difference*0.5f);
				sf::Color fadeColor(255, 200, 10, 0);
				addParticles(gParticles, 4, ppos, ppos, pi->position-pi->oldPosition, pj->position-pj->oldPosition, 0.998f, 60, 1.0f, pi->sprite.getColor(), pj->sprite.getColor(), &fadeColor);
			}
		}

		// convert to bigger "good" ghost
		for(size_t i=0;i<vec.size();i++){
			if(vec[i].scaleRate>0.001f){
				float s = vec[i].scaleRate>GHOST_SCALE_RATE?GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
			}else if(vec[i].scaleRate<-0.001f){
				float s = vec[i].scaleRate<-GHOST_SCALE_RATE?-GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
				if(vec[i].scaleRate>=-0.001f){ //it is now a dead ghost.
					vec.erase(vec.begin()+i--);
				}
			}else{
				for(size_t j=i+1;j<vec.size();j++){
					//fixed double testing i/j
					//now bad ghosts can get bigger as well!
					if(vec[j].scaleRate>=0.0001f || vec[j].scaleRate<=-0.0001f) continue; //only scale up when not scaling itself.
					if ((vec[i].m_GoodAmnt == GOOD_MAXIMUM && vec[j].m_GoodAmnt == GOOD_MAXIMUM && GoodGhosts > GHOST_MINIMUM_FOR_GOOD_SCALE) || (vec[i].m_GoodAmnt==0 && vec[j].m_GoodAmnt==0))
					{
						if (vec[i].sprite.getScale().x >= GHOST_MAX_SCALE) break;

						float distanceBetweenX = vec[i].position.x - vec[j].position.x;
						float distanceBetweenY = vec[i].position.y - vec[j].position.y;

						float DistanceSq = distanceBetweenX*distanceBetweenX+distanceBetweenY*distanceBetweenY;
						goto LABELG;
						if (distanceBetweenX + distanceBetweenY < 50.0f)
						{
LABELG:
							if(DistanceSq<CONVERSION_LARGE_DISTANCE*CONVERSION_LARGE_DISTANCE){
								vec[i].scaleRate = (vec[j].sprite.getScale().x-1.0f)+GHOST_GROW_RATE;
								vec[j].scaleRate = -vec[j].sprite.getScale().x;
								goto LABELH;
								vec[i].sprite.setScale(vec[i].sprite.getScale().x + (vec[j].sprite.getScale().x - 1.0f) + 0.5f, vec[i].sprite.getScale().y + (vec[j].sprite.getScale().y - 1.0f) + 0.5f);
								vec[i].radius += 0.5f;
								vec[j] = vec[vec.size() - 1];
								vec.pop_back();
								GoodGhosts--;
LABELH:
								break;
							}
						}
					}
				}
			}
		}

	}
	return GoodGhosts;
}

int ghostAdd(std::vector <Ghost> &vec, sf::Vector2f position, sf::Vector2f velocity, sf::Texture &textureBall, int GoodAmnt){
	Ghost gh;
	gh.position = position;
	gh.oldPosition = position-velocity;
	gh.forces = sf::Vector2f(0, -0.001);
	gh.invmass = 1;
	gh.radius = GHOST_RADIUS;
	gh.scaleRate = 0.0f;
	gh.m_GoodAmnt = GoodAmnt;
	gh.sprite.setTexture(textureBall);
	gh.sprite.setColor(sf::Color((int)position.x%256,(int)position.y%256,rand()%256,200));

	// add some particles
	sf::Color fadeColor = sf::Color::White;
	fadeColor.a = 0;
	addParticles(gParticles, 10, position, position, sf::Vector2f(-2.0f, -2.0f), sf::Vector2f(2.0f, 2.0f), 0.998f, 100, 1.0f, gh.sprite.getColor(), sf::Color::White, &fadeColor);


	vec.push_back(gh);
	return vec.size()-1; //return index of ghost.
}

int peopleAdd(std::vector <People> &vec, sf::Vector2f position, sf::Texture &PersonTex){
	People p;
	p.position = position;
	p.sprite.setTexture(PersonTex);
	p.radius = PERSON_RADIUS;
	p.m_Flag = rand()%100<50?PERSON_FACE_LEFT:0;
	p.sprite.setColor(sf::Color(255,255,255,100));
	vec.push_back(p);
	return vec.size()-1; //return index of person.
}

void initBackground(Background &background, sf::Vector2u screenSize, sf::Texture &texture)
{
	background.baseColor = sf::Color(180, 200, 215); // 85, 128, 160); //
	background.pulseState = 0.0f;

	background.buffer.create(screenSize.x, screenSize.y, background.baseColor);
	background.texture.create(screenSize.x, screenSize.y);

	int numShadowGhosts = 7;

	for(int i = 0; i < numShadowGhosts; ++i)
	{
		ShadowGhost shadowGhost;
		shadowGhost.fadeDuration = (randomFloat() * 25.0f) + 10.0f;
		shadowGhost.maxVisibility = (randomFloat() * 0.35f) + 0.1f;
		shadowGhost.fadeState = (randomFloat() * shadowGhost.fadeDuration);
		shadowGhost.sprite.setTexture(texture);
		shadowGhost.sprite.setPosition(randomVector(screenSize));

		background.shadowGhosts.push_back(shadowGhost);
	}
}

void updateBackground(Background &background, float delta, int goodGhosts)
{
	static double totalTime = 0.0f;
	totalTime += delta;

	sf::Color bgColor = background.baseColor;

	float durationOfPulse = 10.0f;
	float halfDuration = (durationOfPulse * 0.5f);

	float state = fmod(totalTime, (double)durationOfPulse);

	if(state > halfDuration) background.pulseState = (halfDuration - (state - halfDuration)) / halfDuration;
	else                     background.pulseState = (state / halfDuration);

	if(goodGhosts > 2) goodGhosts -= 2;

	float redVariance = 20.0f + (7.0f * std::min(goodGhosts, 5));
	float variance = 30.0f;

	//Darken the room slowly and back.
	bgColor.r -= uint8_t(std::min(float(bgColor.r), redVariance) * background.pulseState);
	bgColor.g -= uint8_t(std::min(float(bgColor.g), variance) * background.pulseState);
	bgColor.b -= uint8_t(std::min(float(bgColor.b), variance) * background.pulseState);

	for(int y = 0; y < background.buffer.getSize().y; ++y)
	{
		for(int x = 0; x < background.buffer.getSize().x; ++x)
		{
			background.buffer.setPixel(x, y, bgColor);
		}
	}

	background.texture.update(background.buffer);
}

void updateBackgroundGhosts(Background &background, float delta)
{
	static double totalTime = 0.0f;
	totalTime += delta;

	sf::Vector2f movementAmount(100.0f * delta, 100.0f * delta);

	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];

		float state = fmod(totalTime, (double)shadowGhost.fadeDuration);
		float halfDuration = (shadowGhost.fadeDuration * 0.5f);

		if(state > halfDuration) shadowGhost.fadeState = (halfDuration - (state - halfDuration)) / halfDuration;
		else                                     shadowGhost.fadeState = (state / halfDuration);


		//shadowGhost.sprite.move(movementAmount);
		shadowGhost.sprite.setScale(0.5f + shadowGhost.fadeState, 0.5f + shadowGhost.fadeState);

		//Wave
		sf::Vector2f newPos(0,0);
		float randomNumber =  randomFloat()*30 + 10;

		newPos.y = -sin(totalTime * 3) * delta * randomNumber;
		newPos.x =  sin(totalTime * 3) * delta * randomNumber;

		shadowGhost.sprite.move(newPos+movementAmount);

		//If out of bounds (towards the lower-right of the screen)...
		if(shadowGhost.sprite.getPosition().x > (background.buffer.getSize().x + 100.0f)
			|| shadowGhost.sprite.getPosition().y > (background.buffer.getSize().y + 100.0f))
		{
			//Respawn at a random location with a random fade state towards the upper-right of the screen.
			shadowGhost.fadeState = (randomFloat() * 1.0f);
			shadowGhost.sprite.setPosition(randomFloat() * float(background.buffer.getSize().x) - 200.0f,
				randomFloat() * float(background.buffer.getSize().y) - 200.0f);
		}
	}
}

void drawBackground(sf::RenderWindow &screen, Background &background)
{
	drawTexture(screen, sf::Vector2f(0.0f, 0.0f), background.texture);
}

void drawBackgroundGhosts(sf::RenderTarget &screen, Background &background)
{
	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];
		shadowGhost.sprite.setColor(sf::Color(0, int(32.0f + (64.0f * shadowGhost.maxVisibility)),
			int(96.0f + (64.0f * shadowGhost.maxVisibility)), int(shadowGhost.fadeState * shadowGhost.maxVisibility * 255.0f)));
		screen.draw(shadowGhost.sprite);
	}
}

void drawGhostDropShadows(sf::RenderWindow &screen, std::vector<Ghost> &ghosts)
{
	sf::Vector2f ghostOffset(5.0f, 7.0f);//5.0f,5.0f);

	for(size_t i = 0; i < ghosts.size(); ++i)
	{
		double rad = ghosts[i].radius;
		ghosts[i].sprite.setPosition(ghosts[i].position - sf::Vector2f(rad, rad) + ghostOffset);
		ghosts[i].sprite.setColor(sf::Color(85, 128, 160, ghosts[i].m_GoodAmnt * 4 % 256));
		screen.draw(ghosts[i].sprite);
	}
}

void updateParticles(std::vector<Particle> *particles) {

	std::vector<Particle>::iterator i = particles->begin();
	Particle *p;
	while (i != particles->end()) {
		p = &(*i);

		if (p->lifetime == 0) {
			i = particles->erase(i);
			continue;
		}

		// euler, no acceleration for now
		p->position += p->velocity;
		p->velocity *= p->friction;
		p->rotation += p->omega;

		p->lifetime--;

		++i;
	}

}

void drawParticles(sf::RenderTarget *screen, std::vector<Particle> &particles, const sf::Texture &texture) {
	for (size_t i=0;i<particles.size();++i) {
		sf::Color color;
		if (particles[i].color != particles[i].endColor)
			color = fadeColors(particles[i].color, particles[i].endColor, 1.0f - std::max(0.0f, std::min(particles[i].lifetime / (float)particles[i].energy, 1.0f)));
		else
			color = particles[i].color;

		// this could be faster
		drawTexture(*screen, particles[i].position, texture, sf::IntRect(), color, particles[i].rotation);

	}
}

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const float energyScale, const sf::Color colorMin, const sf::Color colorMax, sf::Color *fadeColor) {
	sf::Vector2f pdiff = posMax - posMin;
	sf::Vector2f vdiff = velMax - velMin;

	for (int i=0;i<count;++i) {
		Particle p;
		p.position = randomVector(posMin, posMax);
		p.velocity = randomVector(velMin, velMax);
		p.friction = friction;
		p.rotation = randomFloat()*PI*2.0f;
		p.omega = randomRange(-4.0f*PI, 4.0f*PI);

		// life time is in ticks
		p.lifetime = lifetime;
		p.energy = lifetime*energyScale;

		float r = randomFloat();
		p.color = colorMin;
		p.color.r += r*(colorMax.r - colorMin.r);
		p.color.g += r*(colorMax.g - colorMin.g);
		p.color.b += r*(colorMax.b - colorMin.b);
		p.color.a += r*(colorMax.a - colorMin.a);

		if (fadeColor != 0)
			p.endColor = *fadeColor;
		else
			p.endColor = p.color;

		particles->push_back(p);
	}
}

void pingPongGhostBuffers(sf::RenderTexture *buffers, const sf::Color &clearColor) {
	int lastRenderTarget = currentRenderTarget;
	currentRenderTarget = !currentRenderTarget;
	buffers[currentRenderTarget].clear(clearColor);
	buffers[lastRenderTarget].display();
	// "ghost" the other buffer onto the fresh one
	drawTexture(buffers[currentRenderTarget], sf::Vector2f(0.0f, 0.0f), buffers[lastRenderTarget].getTexture(), sf::IntRect(), sf::Color(255, 255, 255, GHOST_BUFFER_FADE), 0.0f, false, false, sf::BlendNone);

}

// forward declaration
void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
	sf::Texture &texture, sf::Texture &People_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles, sf::Font &GameFont, sf::RenderTexture *ghostBuffers);

int main()
{
	std::srand(static_cast<unsigned>(std::time(0)));
	sf::RenderWindow screen(sf::VideoMode(800, 600, 32), "Ghost Horror Code");
	screen.setFramerateLimit(60);

	//Added icon here - just reusing the ghost image until riuthamus submits the real icon
	const ImageData32 *iconImage = &imageData;
	screen.setIcon(iconImage->width, iconImage->height, iconImage->pixel_data);

	sf::Image image, imageBall;
	image.create(imageData.width, imageData.height, imageData.pixel_data);
	image.createMaskFromColor(sf::Color::Black, 0);

	sf::Image PersonImage;
	PersonImage.create(Person_A.width, Person_A.height, Person_A.pixel_data);
	PersonImage.createMaskFromColor(sf::Color::Black, 0);

	sf::Texture texture;
	sf::Texture PersonTex;
	sf::Texture particleTex;

	texture.loadFromImage(image);
	texture.setSmooth(true);
	PersonTex.loadFromImage(PersonImage);
	PersonTex.setSmooth(true);

	sf::Sprite sprite;
	sf::Vector2f position = randomVector(screen.getSize() - image.getSize());
	sf::Vector2f Velocity = randomVector(sf::Vector2f(-1.0f, -1.0f), sf::Vector2f(1.0f, 1.0f));

	//Add out game font!
	sf::Font m_GameFont;
	m_GameFont.loadFromMemory(InconcolataFont, sizeof(InconcolataFont));

	Background background;
	initBackground(background, screen.getSize(), texture);

	uchar pdata[64];
	memset(pdata, 255, 64); // not quite what I expected, but it's good for now lol
	sf::Image pimage;
	// Since it should be 4 channels, proper image added.
	pimage.create(8, 8, particleData);
	particleTex.loadFromImage(pimage);

	currentRenderTarget = 1;
	sf::RenderTexture ghostBuffers[2];
	for (int i=0;i<2;++i) // yep just did a for loop for 2! 8]
	{
		ghostBuffers[i].create(screen.getSize().x, screen.getSize().y);
		ghostBuffers[i].clear(sf::Color(255, 255, 255, 0));
	}


	goto LABELA;
	sprite.setTexture(texture);
	sprite.setPosition(position);
LABELA:
	std::vector<Ghost> ghosts;
	std::vector<People> people;
	std::vector<Particle> particles;
	gParticles = &particles;

	goto LABELK;
	//spawn initial 3 ghosts.
	for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
	//spawn a dude!
	peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), PersonTex);
LABELK:
	loop(screen, background, position, Velocity, image, sprite, texture, PersonTex, particleTex, ghosts, people, &particles, m_GameFont, ghostBuffers);
}

void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
	sf::Texture &texture, sf::Texture &Person_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles, sf::Font &GameFont, sf::RenderTexture *ghostBuffers) {

		//don't want to thrash the stack with the tail recursion
		static sf::Clock clock;
		static unsigned int SpawnTick = GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
		static int HighScore = 0;
		static int ActiveScore = 0;
		static int LastHighScore = 0;
		static int GameTicks = 0;
		static int GameState = STATE_MENU;
		static std::vector<Ghost *> allGoodGhosts;
		static sf::Color gameOverTextColors[4] = {sf::Color(255, 0, 0), sf::Color(0, 255, 0), sf::Color(0, 0, 255), sf::Color(255, 200, 0)};
		static int gameOverColorIndex[2] = {0,1};
		static float gameOverColorFade = 0.0f;
		bool running = true;
		mousePosition = sf::Vector2u(screen.getSize().x/2, screen.getSize().y/2);

		//Game Text
		// Replacement for below..
		static sf::Text ScoreText, PlayText, gameOverText;
		ScoreText.setFont(GameFont);
		PlayText.setFont(GameFont);
		gameOverText.setFont(GameFont);
		PlayText.setString("Play");
		gameOverText.setString("\tGame Over!\nClick to play again");
		// Not really sure why these lines crash on me, but the above works fine and achieves the same thing, meh.
		//static sf::Text ScoreText("", GameFont);
		//static sf::Text PlayText("Play", GameFont);
		//Position PlayText
		sf::Rect<float> PlayBounds = PlayText.getLocalBounds();
		PlayText.setPosition(screen.getSize().x*0.5f-PlayBounds.width*0.5f, screen.getSize().y*0.5f-PlayBounds.height*0.5f);
		gameOverText.setPosition(screen.getSize().x*0.5f-gameOverText.getLocalBounds().width*0.5f, screen.getSize().y*0.5f-gameOverText.getLocalBounds().height*0.5f);
		static std::ostringstream ScoreString;
		ScoreText.setString(ScoreString.str());
		while(running){
			float deltaTime = clock.getElapsedTime().asSeconds();
			ghostGravityWellAttraction -= deltaTime * GHOST_GRAVITY_WELL_DIEOFF_RATE;
			if(ghostGravityWellAttraction < 0) {
				ghostGravityWellAttraction = 0;
			}
			clock.restart();

			sf::Event event;
			while (screen.pollEvent(event))
			{
				if (event.type == sf::Event::Closed)
				{
					running = false;
				}else
					if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
					{
						running = false;
					}else
						if (event.type == sf::Event::MouseMoved)
						{
							mousePosition = sf::Vector2u(event.mouseMove.x, event.mouseMove.y);
							ghostGravityWellAttraction = 1;
						}else
							if(event.type == sf::Event::MouseButtonPressed){
								if(GameState==STATE_MENU && PlayText.getGlobalBounds().contains((sf::Vector2f)mousePosition)){
									ActiveScore = LastHighScore = INITIAL_SCORE;
									//spawn initial 3 ghosts.
									for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
									//spawn a dude!
									peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), Person_ATex);
									GameState=STATE_PLAYING;
								}
								if (GameState == GameStateGameOver) {
									ActiveScore = INITIAL_SCORE;
									//spawn initial 3 ghosts.
									for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
									//spawn a dude!
									peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), Person_ATex);
									GameState=STATE_PLAYING;

								}
							}
			}
			goto LABELB;
			position+=Velocity;
			if(position.x<0.0f){
				position.x = 0.0f;
				Velocity.x = -Velocity.x;
			}else if(position.x>=(float)(screen.getSize().x-image.getSize().x)){
				position.x = (float)(screen.getSize().x-image.getSize().x);
				Velocity.x = -Velocity.x;
			}
			if(position.y<0.0f){
				position.y = 0.0f;
				Velocity.y = -Velocity.y;
			}else if(position.y>=(float)(screen.getSize().y-image.getSize().y)){
				position.y = (float)(screen.getSize().y-image.getSize().y);
				Velocity.y = -Velocity.y;
			}
			sprite.setPosition(position);  //Good bye old crap.
LABELB:
			allGoodGhosts.clear();
			int goodGhosts = ghostAdvance(ghosts, allGoodGhosts, screen.getSize());
			updateBackground(background, deltaTime, goodGhosts);
			updateBackgroundGhosts(background, deltaTime);
			updateParticles(particles);

			screen.clear();
			drawBackground(screen, background);

			// Ping pong between ghost buffers
			pingPongGhostBuffers(ghostBuffers, sf::Color(255, 255, 255, 0));

			drawBackgroundGhosts(ghostBuffers[currentRenderTarget], background);
			//Let's draw particles here!
			goto LABELW;
LABELX:

			ghostBuffers[currentRenderTarget].display();
			drawTexture(screen, sf::Vector2f(0.0f, 0.0f), ghostBuffers[currentRenderTarget].getTexture());

			drawGhostDropShadows(screen, ghosts);


			goto LABELC;
			screen.draw(sprite);
LABELC:
			//draw people!
			for(size_t i=0;i<people.size();i++){
				float rad = people[i].radius;
				people[i].sprite.setPosition(people[i].position-sf::Vector2f(rad, rad));
				people[i].sprite.setScale((people[i].m_Flag&PERSON_FACE_LEFT)?-1.0f:1.0f, 1.0f);
				screen.draw(people[i].sprite);
			}

			//int GoodIncrement = 0;
			//int BadIncrement = 0;
			for(size_t i=0;i<ghosts.size();i++){
				double rad = ghosts[i].radius;
				ghosts[i].sprite.setPosition(ghosts[i].position-sf::Vector2f(rad, rad));
				ghosts[i].sprite.setColor(sf::Color(GOOD_MAXIMUM-ghosts[i].m_GoodAmnt, 0, ghosts[i].m_GoodAmnt, 25+ghosts[i].m_GoodAmnt * 4 % 231 ));
				screen.draw(ghosts[i].sprite);

				//Do score calculations!
				if(GameState==STATE_PLAYING) ActiveScore+=(ghosts[i].m_GoodAmnt>=GOOD_MINIMUM?GOOD_GHOST_SCORE_VALUE:-BAD_GHOST_SCORE_VALUE)*(ghosts[i].sprite.getScale().x+(ghosts[i].sprite.getScale().x-1.0f)*2.0f);
				else ghosts[i].scaleRate=-ghosts[i].sprite.getScale().x; //destroy all ghosts when in the menu
			}
			HighScore = ActiveScore>HighScore?ActiveScore:HighScore;
			LastHighScore = ActiveScore>LastHighScore?ActiveScore:LastHighScore;
			goto GAMEOVERCHECK;
			if(ActiveScore<=0) GameState=STATE_MENU;
GAMEOVERCHECK:
			if (ActiveScore <= 0) {
				for (int i=0;i<goodGhosts;++i) {
					allGoodGhosts[i]->m_GoodAmnt -= 2.0f*BAD_CONVERSION_RATE;
				}
				ActiveScore = 0;
			}
			if (GameState == GameStatePlaying && goodGhosts <= 0) GameState = GameStateGameOver;


			ScoreString.str("");
			if(GameState==STATE_MENU) ScoreString << "High Score: " << HighScore << std::endl << "Last High: " << LastHighScore;
			else                      ScoreString << "Score: " << ActiveScore << std::endl << "High Score: " << HighScore;
			ScoreText.setString(ScoreString.str());
			goto LABELG;
			if(rand()%50 == 0 || rand() % 60 >= 57) //decreased rate of spawning.
LABELG:
			if(GameState==STATE_MENU){
				if(PlayText.getGlobalBounds().contains((sf::Vector2f)mousePosition)) PlayText.setColor(sf::Color(255, 0, 0));
				else PlayText.setColor(sf::Color(255,255,255));
				screen.draw(PlayText);

			} else if (GameState == GameStateGameOver) {
				gameOverColorFade += 0.02f;
				if (gameOverColorFade >= 1.0f) {
					gameOverColorIndex[0] = gameOverColorIndex[1];
					int count;
					
					while ((gameOverColorIndex[1] = round(randomFloat()*3)) == gameOverColorIndex[0] && count++ < 10);
					gameOverColorFade = 0.0f;
				}
				sf::Color c = fadeColors(gameOverTextColors[gameOverColorIndex[0]], gameOverTextColors[gameOverColorIndex[1]], gameOverColorFade);
				gameOverText.setColor(c);
				screen.draw(gameOverText);

			}else{
				if(SpawnTick==0){
					ghostAdd(ghosts, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)screen.getSize()),
						sf::Vector2f(rand()%20-10, rand()%20-10), texture, 0);
					SpawnTick=GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
				}else{
					//The longer the game goes on, the faster we spawn.
					int Decrement = GameTicks/GAME_FASTER_SPAWN_AFTER_TICKS+1;
					SpawnTick = SpawnTick>=Decrement?SpawnTick-Decrement:0;
				}
			}
			GameTicks++;
			goto LABELY;
LABELW:
			drawParticles(&ghostBuffers[currentRenderTarget], *particles, particleTex);
			goto LABELX;
LABELY:
			screen.draw(ScoreText);

			screen.display();
		}

		if (running) {
			loop(screen, background, position, Velocity, image, sprite, texture, particleTex, Person_ATex, ghosts, people, particles, GameFont, ghostBuffers);
		}
}

#error "Be sure to add resources here!"
see attachment for full file.

also, video:


#1slicer4ever

Posted 16 November 2013 - 02:47 PM

Excellent work fuzzy, had to make a slight modification for msvc(cmath does not include round):
 
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <vector>
#include <cmath>
#include <stdint.h>
#include <iostream>
#include <cstring>
#include <sstream>

typedef unsigned int uint; // laziness
typedef unsigned char uchar; // more

#ifndef round
double round(double d){
	return floor(d+0.5);
}

#endif

union RGBA
{
	struct Channel
	{
		uint8_t red;
		uint8_t green;
		uint8_t blue;
		uint8_t alpha;
	};

	uint32_t rgba;
	Channel channel;
};

struct ImageData32
{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[32 * 32 * 4 + 1];
};

struct ImageData64{
	unsigned int width;
	unsigned int height;
	unsigned char pixel_data[64*64*4+1];
};

struct Ghost
{
	sf::Vector2f position;
	sf::Vector2f oldPosition;
	sf::Vector2f forces;
	float scaleRate;
	float radius;
	float invmass;
	int m_GoodAmnt;
	sf::Sprite sprite;
};

struct ShadowGhost
{
	sf::Sprite sprite;
	float fadeDuration;
	float maxVisibility;
	float fadeState;
};

struct People{
	sf::Vector2f position;
	float radius;
	sf::Sprite sprite;
	unsigned char m_Flag;
};

struct Background
{
	sf::Color baseColor;
	sf::Image buffer;
	sf::Texture texture;
	float pulseState;

	std::vector<ShadowGhost> shadowGhosts;
};

// Simple "self-sufficient" particles
struct Particle
{
	sf::Vector2f position, velocity;
	float friction;
	float rotation, omega;
	sf::Color color;
	sf::Color endColor;
	uint lifetime;
	uint energy;
};

extern const uchar particleData[];
extern const ImageData32 imageData;
extern const ImageData64 Person_A;
extern const unsigned char InconcolataFont[58464];

#define PLAYER_GHOST 0
#define GHOST_GOOD 1
#define CONVERSION_DISTANCE 80.0f
#define CONVERSION_LARGE_DISTANCE 50.0f
#define GOOD_MINIMUM 100
#define GOOD_MAXIMUM 255
#define BAD_CONVERSION_RATE 6
#define GOOD_CONVERSION_RATE 2
#define GHOST_RADIUS 16.0f
#define GHOST_GROW_RATE 0.2
#define GHOST_SPAWN_MIN_TICKS 30 //0.5 seconds at 60 fps
#define GHOST_SPAWN_MAX_TICKS 120 //2 seconds at 60 fps
#define GHOST_MAX_SCALE 1.8
#define GHOST_MINIMUM_FOR_GOOD_SCALE 5
#define GHOST_SCALE_RATE 0.01f
#define INITIAL_SCORE 3000
#define GOOD_GHOST_SCORE_VALUE 1
#define BAD_GHOST_SCORE_VALUE 1
#define GAME_FASTER_SPAWN_AFTER_TICKS (45*60) //every 45 seconds(60 ticks per second), ghosts begin spawning slightly faster.

typedef enum {
	GameStateMenu = 0,
	GameStatePlaying,
	GameStateGameOver,
} GameState;

#define STATE_MENU GameStateMenu
#define STATE_PLAYING GameStatePlaying

#define PERSON_RADIUS 32.0f
#define PERSON_FACE_LEFT 1

#define GHOST_BUFFER_BLUR_X     16.0f
#define GHOST_BUFFER_BLUR_Y     16.0f
#define GHOST_BUFFER_FADE       240

#define PI                      3.1415926535897f

static sf::Vector2u mousePosition;
static float ghostGravityWellAttraction = 0;
static std::vector<Particle> *gParticles;    // yay global reference
static uint currentRenderTarget;

#define MASS 2 * 1e-2
#define GHOST_GRAVITY_WELL_DIEOFF_RATE (1.0f / 30.0f)

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const float energyScale, const sf::Color colorMin, const sf::Color colorMax, sf::Color *fadeColor=0);

float randomFloat()
{
	return std::rand()/(float)RAND_MAX; //get out of here swiftcoder!
	return 4.0f;//std::rand() / static_cast<float>(RAND_MAX);
}

inline float randomRange(const float min, const float max) {
	return min + (max-min)*randomFloat();
}

sf::Vector2f randomVector(sf::Vector2u bounds)
{
	return sf::Vector2f(randomFloat() * bounds.x, randomFloat() * bounds.y);
}

//return random vector between min/max....although since randomFloat returns 4, more like min+max*4....
sf::Vector2f randomVector(sf::Vector2f min, sf::Vector2f max){
	//sf::Vector2f Vec = min+(max-min);
	//return sf::Vector2f(Vec.x*randomFloat(), Vec.y*randomFloat());
	sf::Vector2f diff = max-min;
	return min + sf::Vector2f(diff.x*randomFloat(), diff.y*randomFloat());
}

sf::Color fadeColors(const sf::Color &start, const sf::Color &end, const float amount) {
	sf::Color color;
	color.r = start.r + amount*int(end.r - start.r);
	color.g = start.g + amount*int(end.g - start.g);
	color.b = start.b + amount*int(end.b - start.b);
	color.a = start.a + amount*int(end.a - start.a);
	return color;
}

//Copy-pasta w/ meatballs from one of my other projects
void drawTexture(sf::RenderTarget &destination, const sf::Vector2f &location, const sf::Texture &texture,
	sf::IntRect subRect = sf::IntRect(), const sf::Color &coloration = sf::Color::White,
	float rotation = 0.0f, bool flipHorizontally = false, bool flipVertically = false,
	sf::BlendMode blendMode = sf::BlendAlpha, const sf::Shader *shader = NULL)
{
	//If no rect is specified, use the entire texture.
	if(subRect.width == 0 || subRect.height == 0)
	{
		subRect.top = 0;
		subRect.left = 0;
		subRect.width = texture.getSize().x;
		subRect.height = texture.getSize().y;
	}

	//Set the position in space.
	sf::Transform translation;
	translation.translate(location);

	//Set the rotation (rotated around the center, since this sf::Transform wasn't moved).
	sf::Transform rotationTransform;
	rotationTransform.rotate(rotation);

	//Setup the render state.
	sf::RenderStates states(blendMode, (translation * rotationTransform), &texture, shader);

	//Setup the vertices and their attributes.
	sf::Vertex vertices[4];

	//The transparency:
	vertices[0].color = coloration;
	vertices[1].color = coloration;
	vertices[2].color = coloration;
	vertices[3].color = coloration;

	//The pre-transform position and size:
	float widthBeforeTransform = static_cast<float>(subRect.width);
	float heightBeforeTransform = static_cast<float>(subRect.height);
	vertices[0].position = sf::Vector2f(0, 0);
	vertices[1].position = sf::Vector2f(0, heightBeforeTransform);
	vertices[2].position = sf::Vector2f(widthBeforeTransform, heightBeforeTransform);
	vertices[3].position = sf::Vector2f(widthBeforeTransform, 0);

	//Calculate the texture coordinates:
	float left   = static_cast<float>(subRect.left);
	float right  = left + subRect.width;
	float top    = static_cast<float>(subRect.top);
	float bottom = top + subRect.height;

	//If we're mirroring, swap the texture coordinates vertically and/or horizontally.
	if(flipVertically)        std::swap(top, bottom);
	if(flipHorizontally)    std::swap(left, right);

	//Set the texture coordinates:
	vertices[0].texCoords = sf::Vector2f(left, top);
	vertices[1].texCoords = sf::Vector2f(left, bottom);
	vertices[2].texCoords = sf::Vector2f(right, bottom);
	vertices[3].texCoords = sf::Vector2f(right, top);

	//Use the sf::RenderTarget to draw the vertices using the sf::RenderStates we set up.
	destination.draw(vertices, 4, sf::Quads, states);
}


//returns good ghost counter.
unsigned int ghostAdvance(std::vector <Ghost> &vec, std::vector<Ghost *> &good, sf::Vector2u screenSize){
	unsigned int GoodGhosts = 0;
	// gravity well test (it is a feature)
	//now it's gameplay!
	for (size_t i = 0; i < vec.size(); ++i)
	{
		goto LABELE;
		if (i == PLAYER_GHOST) continue; // if you remove this a ghost will die
LABELE:
		if(vec[i].m_GoodAmnt<GOOD_MINIMUM) continue;
		Ghost *p = &(vec[i]);

		sf::Vector2f r = p->position - sf::Vector2f(mousePosition.x, mousePosition.y);
		r.x = r.x / screenSize.x;
		r.y = r.y / screenSize.y;

		double len2 = pow(r.x, 2) + pow(r.y, 2);
		r = sf::Vector2f(r.x / sqrt(len2), r.y / sqrt(len2));

		const float MIN = 0.02;
		if (len2 < MIN) len2 = MIN;

		double ax = r.x * (+1) * MASS / len2; // physics
		double ay = r.y * (+1) * MASS / len2;

		p->forces = sf::Vector2f(ax, ay) * ghostGravityWellAttraction;
		GoodGhosts++;
		good.push_back(p);
	}

	for(size_t i=0;i<vec.size();i++){
		Ghost *p = &(vec[i]);
		//Verlet integration
		sf::Vector2f oldPos = p->position;
		p->position += p->position - (p->oldPosition + (p->forces * 0.5f));
		p->oldPosition = oldPos;

		//Wall collision detection
		double overY = 0;
		if(p->position.y > screenSize.y-p->radius)
			overY = (screenSize.y-p->radius) - p->position.y;
		if(p->position.y < p->radius)
			overY = (p->radius) - p->position.y;
		if(p->position.x < p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = p->radius;
		}
		if(p->position.x > screenSize.x-p->radius){
			p->oldPosition.x = p->position.x;
			p->position.x = screenSize.x-p->radius;
		}

		//Friction with floor
		if(overY != 0){
			p->oldPosition.y = p->position.y;
			p->position.y += overY;
			double xVel = p->position.x - p->oldPosition.x;
			if(xVel != 0)
				p->position.x -= (xVel * 0.1);
		}
	}
	//Ghost-Ghost collision detection
	for(size_t i=0;i<vec.size();i++){
		//fixed j to i+1
		for(size_t j=i+1;j<vec.size();j++){
			Ghost *pi = &(vec[i]);
			Ghost *pj = &(vec[j]);

			float dx = pj->position.x-pi->position.x;
			float dy = pj->position.y-pi->position.y;
			float a = dx*dx+dy*dy;
			float l = (pi->radius + pj->radius);
			//do conversion if within distance.
			if(a<=CONVERSION_DISTANCE*CONVERSION_DISTANCE){
				int BadRate = GoodGhosts>3?BAD_CONVERSION_RATE:0;
				if((vec[i].m_GoodAmnt>=GOOD_MINIMUM && vec[j].m_GoodAmnt<GOOD_MINIMUM)){ //i is good, j is bad
					vec[i].m_GoodAmnt -= BadRate * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM && vec[j].m_GoodAmnt>=GOOD_MINIMUM){
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BadRate * vec[i].sprite.getScale().x;
				}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM){ //both i and j are bad.
					vec[i].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt -= BAD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}else{ //both are good.
					vec[i].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[j].sprite.getScale().x;
					vec[j].m_GoodAmnt += GOOD_CONVERSION_RATE * vec[i].sprite.getScale().x;
				}
				vec[i].m_GoodAmnt = vec[i].m_GoodAmnt<0?0:vec[i].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[i].m_GoodAmnt;
				vec[j].m_GoodAmnt = vec[j].m_GoodAmnt<0?0:vec[j].m_GoodAmnt>GOOD_MAXIMUM?GOOD_MAXIMUM:vec[j].m_GoodAmnt;
			}
			if(a <= l*l ){
				bool massfix=false;
				if(pi->invmass == 0 && pj->invmass == 0){
					massfix = true;
					pi->invmass = pj->invmass = 1;
				}
				if(a==0) continue;
				float dist = sqrt(a);
				float difference = (dist - l) / (dist*(pi->invmass+pj->invmass));

				pi->position.x += pi->invmass * dx * difference * 0.5;
				pi->position.y += pi->invmass * dy * difference * 0.5;
				pj->position.x -= pj->invmass * dx * difference * 0.5;
				pj->position.y -= pj->invmass * dy * difference * 0.5;

				if(massfix){
					pi->invmass = pj->invmass = 0;
				}
				goto LABELF;
				if(i==PLAYER_GHOST){
					//ghost hit player!
					vec.erase(vec.begin()+j--);
					continue;
				}
LABELF:;

				sf::Vector2f ppos = pi->position + sf::Vector2f(dx*difference*0.5f, dy*difference*0.5f);
				sf::Color fadeColor(255, 200, 10, 0);
				addParticles(gParticles, 4, ppos, ppos, pi->position-pi->oldPosition, pj->position-pj->oldPosition, 0.998f, 60, 1.0f, pi->sprite.getColor(), pj->sprite.getColor(), &fadeColor);
			}
		}

		// convert to bigger "good" ghost
		for(size_t i=0;i<vec.size();i++){
			if(vec[i].scaleRate>0.001f){
				float s = vec[i].scaleRate>GHOST_SCALE_RATE?GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
			}else if(vec[i].scaleRate<-0.001f){
				float s = vec[i].scaleRate<-GHOST_SCALE_RATE?-GHOST_SCALE_RATE:vec[i].scaleRate;
				vec[i].sprite.setScale(vec[i].sprite.getScale()+sf::Vector2f(s,s));
				vec[i].scaleRate-=s;
				vec[i].radius = GHOST_RADIUS*vec[i].sprite.getScale().x;
				if(vec[i].scaleRate>=-0.001f){ //it is now a dead ghost.
					vec.erase(vec.begin()+i--);
				}
			}else{
				for(size_t j=i+1;j<vec.size();j++){
					//fixed double testing i/j
					//now bad ghosts can get bigger as well!
					if(vec[j].scaleRate>=0.0001f || vec[j].scaleRate<=-0.0001f) continue; //only scale up when not scaling itself.
					if ((vec[i].m_GoodAmnt == GOOD_MAXIMUM && vec[j].m_GoodAmnt == GOOD_MAXIMUM && GoodGhosts > GHOST_MINIMUM_FOR_GOOD_SCALE) || (vec[i].m_GoodAmnt==0 && vec[j].m_GoodAmnt==0))
					{
						if (vec[i].sprite.getScale().x >= GHOST_MAX_SCALE) break;

						float distanceBetweenX = vec[i].position.x - vec[j].position.x;
						float distanceBetweenY = vec[i].position.y - vec[j].position.y;

						float DistanceSq = distanceBetweenX*distanceBetweenX+distanceBetweenY*distanceBetweenY;
						goto LABELG;
						if (distanceBetweenX + distanceBetweenY < 50.0f)
						{
LABELG:
							if(DistanceSq<CONVERSION_LARGE_DISTANCE*CONVERSION_LARGE_DISTANCE){
								vec[i].scaleRate = (vec[j].sprite.getScale().x-1.0f)+GHOST_GROW_RATE;
								vec[j].scaleRate = -vec[j].sprite.getScale().x;
								goto LABELH;
								vec[i].sprite.setScale(vec[i].sprite.getScale().x + (vec[j].sprite.getScale().x - 1.0f) + 0.5f, vec[i].sprite.getScale().y + (vec[j].sprite.getScale().y - 1.0f) + 0.5f);
								vec[i].radius += 0.5f;
								vec[j] = vec[vec.size() - 1];
								vec.pop_back();
								GoodGhosts--;
LABELH:
								break;
							}
						}
					}
				}
			}
		}

	}
	return GoodGhosts;
}

int ghostAdd(std::vector <Ghost> &vec, sf::Vector2f position, sf::Vector2f velocity, sf::Texture &textureBall, int GoodAmnt){
	Ghost gh;
	gh.position = position;
	gh.oldPosition = position-velocity;
	gh.forces = sf::Vector2f(0, -0.001);
	gh.invmass = 1;
	gh.radius = GHOST_RADIUS;
	gh.scaleRate = 0.0f;
	gh.m_GoodAmnt = GoodAmnt;
	gh.sprite.setTexture(textureBall);
	gh.sprite.setColor(sf::Color((int)position.x%256,(int)position.y%256,rand()%256,200));

	// add some particles
	sf::Color fadeColor = sf::Color::White;
	fadeColor.a = 0;
	addParticles(gParticles, 10, position, position, sf::Vector2f(-2.0f, -2.0f), sf::Vector2f(2.0f, 2.0f), 0.998f, 100, 1.0f, gh.sprite.getColor(), sf::Color::White, &fadeColor);


	vec.push_back(gh);
	return vec.size()-1; //return index of ghost.
}

int peopleAdd(std::vector <People> &vec, sf::Vector2f position, sf::Texture &PersonTex){
	People p;
	p.position = position;
	p.sprite.setTexture(PersonTex);
	p.radius = PERSON_RADIUS;
	p.m_Flag = rand()%100<50?PERSON_FACE_LEFT:0;
	p.sprite.setColor(sf::Color(255,255,255,100));
	vec.push_back(p);
	return vec.size()-1; //return index of person.
}

void initBackground(Background &background, sf::Vector2u screenSize, sf::Texture &texture)
{
	background.baseColor = sf::Color(180, 200, 215); // 85, 128, 160); //
	background.pulseState = 0.0f;

	background.buffer.create(screenSize.x, screenSize.y, background.baseColor);
	background.texture.create(screenSize.x, screenSize.y);

	int numShadowGhosts = 7;

	for(int i = 0; i < numShadowGhosts; ++i)
	{
		ShadowGhost shadowGhost;
		shadowGhost.fadeDuration = (randomFloat() * 25.0f) + 10.0f;
		shadowGhost.maxVisibility = (randomFloat() * 0.35f) + 0.1f;
		shadowGhost.fadeState = (randomFloat() * shadowGhost.fadeDuration);
		shadowGhost.sprite.setTexture(texture);
		shadowGhost.sprite.setPosition(randomVector(screenSize));

		background.shadowGhosts.push_back(shadowGhost);
	}
}

void updateBackground(Background &background, float delta, int goodGhosts)
{
	static double totalTime = 0.0f;
	totalTime += delta;

	sf::Color bgColor = background.baseColor;

	float durationOfPulse = 10.0f;
	float halfDuration = (durationOfPulse * 0.5f);

	float state = fmod(totalTime, (double)durationOfPulse);

	if(state > halfDuration) background.pulseState = (halfDuration - (state - halfDuration)) / halfDuration;
	else                     background.pulseState = (state / halfDuration);

	if(goodGhosts > 2) goodGhosts -= 2;

	float redVariance = 20.0f + (7.0f * std::min(goodGhosts, 5));
	float variance = 30.0f;

	//Darken the room slowly and back.
	bgColor.r -= uint8_t(std::min(float(bgColor.r), redVariance) * background.pulseState);
	bgColor.g -= uint8_t(std::min(float(bgColor.g), variance) * background.pulseState);
	bgColor.b -= uint8_t(std::min(float(bgColor.b), variance) * background.pulseState);

	for(int y = 0; y < background.buffer.getSize().y; ++y)
	{
		for(int x = 0; x < background.buffer.getSize().x; ++x)
		{
			background.buffer.setPixel(x, y, bgColor);
		}
	}

	background.texture.update(background.buffer);
}

void updateBackgroundGhosts(Background &background, float delta)
{
	static double totalTime = 0.0f;
	totalTime += delta;

	sf::Vector2f movementAmount(100.0f * delta, 100.0f * delta);

	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];

		float state = fmod(totalTime, (double)shadowGhost.fadeDuration);
		float halfDuration = (shadowGhost.fadeDuration * 0.5f);

		if(state > halfDuration) shadowGhost.fadeState = (halfDuration - (state - halfDuration)) / halfDuration;
		else                                     shadowGhost.fadeState = (state / halfDuration);


		//shadowGhost.sprite.move(movementAmount);
		shadowGhost.sprite.setScale(0.5f + shadowGhost.fadeState, 0.5f + shadowGhost.fadeState);

		//Wave
		sf::Vector2f newPos(0,0);
		float randomNumber =  randomFloat()*30 + 10;

		newPos.y = -sin(totalTime * 3) * delta * randomNumber;
		newPos.x =  sin(totalTime * 3) * delta * randomNumber;

		shadowGhost.sprite.move(newPos+movementAmount);

		//If out of bounds (towards the lower-right of the screen)...
		if(shadowGhost.sprite.getPosition().x > (background.buffer.getSize().x + 100.0f)
			|| shadowGhost.sprite.getPosition().y > (background.buffer.getSize().y + 100.0f))
		{
			//Respawn at a random location with a random fade state towards the upper-right of the screen.
			shadowGhost.fadeState = (randomFloat() * 1.0f);
			shadowGhost.sprite.setPosition(randomFloat() * float(background.buffer.getSize().x) - 200.0f,
				randomFloat() * float(background.buffer.getSize().y) - 200.0f);
		}
	}
}

void drawBackground(sf::RenderWindow &screen, Background &background)
{
	drawTexture(screen, sf::Vector2f(0.0f, 0.0f), background.texture);
}

void drawBackgroundGhosts(sf::RenderTarget &screen, Background &background)
{
	for(size_t i = 0; i < background.shadowGhosts.size(); ++i)
	{
		ShadowGhost &shadowGhost = background.shadowGhosts[i];
		shadowGhost.sprite.setColor(sf::Color(0, int(32.0f + (64.0f * shadowGhost.maxVisibility)),
			int(96.0f + (64.0f * shadowGhost.maxVisibility)), int(shadowGhost.fadeState * shadowGhost.maxVisibility * 255.0f)));
		screen.draw(shadowGhost.sprite);
	}
}

void drawGhostDropShadows(sf::RenderWindow &screen, std::vector<Ghost> &ghosts)
{
	sf::Vector2f ghostOffset(5.0f, 7.0f);//5.0f,5.0f);

	for(size_t i = 0; i < ghosts.size(); ++i)
	{
		double rad = ghosts[i].radius;
		ghosts[i].sprite.setPosition(ghosts[i].position - sf::Vector2f(rad, rad) + ghostOffset);
		ghosts[i].sprite.setColor(sf::Color(85, 128, 160, ghosts[i].m_GoodAmnt * 4 % 256));
		screen.draw(ghosts[i].sprite);
	}
}

void updateParticles(std::vector<Particle> *particles) {

	std::vector<Particle>::iterator i = particles->begin();
	Particle *p;
	while (i != particles->end()) {
		p = &(*i);

		if (p->lifetime == 0) {
			i = particles->erase(i);
			continue;
		}

		// euler, no acceleration for now
		p->position += p->velocity;
		p->velocity *= p->friction;
		p->rotation += p->omega;

		p->lifetime--;

		++i;
	}

}

void drawParticles(sf::RenderTarget *screen, std::vector<Particle> &particles, const sf::Texture &texture) {
	for (size_t i=0;i<particles.size();++i) {
		sf::Color color;
		if (particles[i].color != particles[i].endColor)
			color = fadeColors(particles[i].color, particles[i].endColor, 1.0f - std::max(0.0f, std::min(particles[i].lifetime / (float)particles[i].energy, 1.0f)));
		else
			color = particles[i].color;

		// this could be faster
		drawTexture(*screen, particles[i].position, texture, sf::IntRect(), color, particles[i].rotation);

	}
}

void addParticles(std::vector<Particle> *particles, const uint count, const sf::Vector2f &posMin, const sf::Vector2f &posMax, const sf::Vector2f &velMin, const sf::Vector2f &velMax, const float friction, const uint lifetime, const float energyScale, const sf::Color colorMin, const sf::Color colorMax, sf::Color *fadeColor) {
	sf::Vector2f pdiff = posMax - posMin;
	sf::Vector2f vdiff = velMax - velMin;

	for (int i=0;i<count;++i) {
		Particle p;
		p.position = randomVector(posMin, posMax);
		p.velocity = randomVector(velMin, velMax);
		p.friction = friction;
		p.rotation = randomFloat()*PI*2.0f;
		p.omega = randomRange(-4.0f*PI, 4.0f*PI);

		// life time is in ticks
		p.lifetime = lifetime;
		p.energy = lifetime*energyScale;

		float r = randomFloat();
		p.color = colorMin;
		p.color.r += r*(colorMax.r - colorMin.r);
		p.color.g += r*(colorMax.g - colorMin.g);
		p.color.b += r*(colorMax.b - colorMin.b);
		p.color.a += r*(colorMax.a - colorMin.a);

		if (fadeColor != 0)
			p.endColor = *fadeColor;
		else
			p.endColor = p.color;

		particles->push_back(p);
	}
}

void pingPongGhostBuffers(sf::RenderTexture *buffers, const sf::Color &clearColor) {
	int lastRenderTarget = currentRenderTarget;
	currentRenderTarget = !currentRenderTarget;
	buffers[currentRenderTarget].clear(clearColor);
	buffers[lastRenderTarget].display();
	// "ghost" the other buffer onto the fresh one
	drawTexture(buffers[currentRenderTarget], sf::Vector2f(0.0f, 0.0f), buffers[lastRenderTarget].getTexture(), sf::IntRect(), sf::Color(255, 255, 255, GHOST_BUFFER_FADE), 0.0f, false, false, sf::BlendNone);

}

// forward declaration
void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
	sf::Texture &texture, sf::Texture &People_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles, sf::Font &GameFont, sf::RenderTexture *ghostBuffers);

int main()
{
	std::srand(static_cast<unsigned>(std::time(0)));
	sf::RenderWindow screen(sf::VideoMode(800, 600, 32), "Ghost Horror Code");
	screen.setFramerateLimit(60);

	//Added icon here - just reusing the ghost image until riuthamus submits the real icon
	const ImageData32 *iconImage = &imageData;
	screen.setIcon(iconImage->width, iconImage->height, iconImage->pixel_data);

	sf::Image image, imageBall;
	image.create(imageData.width, imageData.height, imageData.pixel_data);
	image.createMaskFromColor(sf::Color::Black, 0);

	sf::Image PersonImage;
	PersonImage.create(Person_A.width, Person_A.height, Person_A.pixel_data);
	PersonImage.createMaskFromColor(sf::Color::Black, 0);

	sf::Texture texture;
	sf::Texture PersonTex;
	sf::Texture particleTex;

	texture.loadFromImage(image);
	texture.setSmooth(true);
	PersonTex.loadFromImage(PersonImage);
	PersonTex.setSmooth(true);

	sf::Sprite sprite;
	sf::Vector2f position = randomVector(screen.getSize() - image.getSize());
	sf::Vector2f Velocity = randomVector(sf::Vector2f(-1.0f, -1.0f), sf::Vector2f(1.0f, 1.0f));

	//Add out game font!
	sf::Font m_GameFont;
	m_GameFont.loadFromMemory(InconcolataFont, sizeof(InconcolataFont));

	Background background;
	initBackground(background, screen.getSize(), texture);

	uchar pdata[64];
	memset(pdata, 255, 64); // not quite what I expected, but it's good for now lol
	sf::Image pimage;
	// Since it should be 4 channels, proper image added.
	pimage.create(8, 8, particleData);
	particleTex.loadFromImage(pimage);

	currentRenderTarget = 1;
	sf::RenderTexture ghostBuffers[2];
	for (int i=0;i<2;++i) // yep just did a for loop for 2! 8]
	{
		ghostBuffers[i].create(screen.getSize().x, screen.getSize().y);
		ghostBuffers[i].clear(sf::Color(255, 255, 255, 0));
	}


	goto LABELA;
	sprite.setTexture(texture);
	sprite.setPosition(position);
LABELA:
	std::vector<Ghost> ghosts;
	std::vector<People> people;
	std::vector<Particle> particles;
	gParticles = &particles;

	goto LABELK;
	//spawn initial 3 ghosts.
	for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
	//spawn a dude!
	peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), PersonTex);
LABELK:
	loop(screen, background, position, Velocity, image, sprite, texture, PersonTex, particleTex, ghosts, people, &particles, m_GameFont, ghostBuffers);
}

void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
	sf::Texture &texture, sf::Texture &Person_ATex, sf::Texture &particleTex, std::vector<Ghost> &ghosts, std::vector<People> &people, std::vector<Particle> *particles, sf::Font &GameFont, sf::RenderTexture *ghostBuffers) {

		//don't want to thrash the stack with the tail recursion
		static sf::Clock clock;
		static unsigned int SpawnTick = GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
		static int HighScore = 0;
		static int ActiveScore = 0;
		static int LastHighScore = 0;
		static int GameTicks = 0;
		static int GameState = STATE_MENU;
		static std::vector<Ghost *> allGoodGhosts;
		static sf::Color gameOverTextColors[4] = {sf::Color(255, 0, 0), sf::Color(0, 255, 0), sf::Color(0, 0, 255), sf::Color(255, 200, 0)};
		static int gameOverColorIndex[2] = {0,1};
		static float gameOverColorFade = 0.0f;
		bool running = true;
		mousePosition = sf::Vector2u(screen.getSize().x/2, screen.getSize().y/2);

		//Game Text
		// Replacement for below..
		static sf::Text ScoreText, PlayText, gameOverText;
		ScoreText.setFont(GameFont);
		PlayText.setFont(GameFont);
		gameOverText.setFont(GameFont);
		PlayText.setString("Play");
		gameOverText.setString("\tGame Over!\nClick to play again");
		// Not really sure why these lines crash on me, but the above works fine and achieves the same thing, meh.
		//static sf::Text ScoreText("", GameFont);
		//static sf::Text PlayText("Play", GameFont);
		//Position PlayText
		sf::Rect<float> PlayBounds = PlayText.getLocalBounds();
		PlayText.setPosition(screen.getSize().x*0.5f-PlayBounds.width*0.5f, screen.getSize().y*0.5f-PlayBounds.height*0.5f);
		gameOverText.setPosition(screen.getSize().x*0.5f-gameOverText.getLocalBounds().width*0.5f, screen.getSize().y*0.5f-gameOverText.getLocalBounds().height*0.5f);
		static std::ostringstream ScoreString;
		ScoreText.setString(ScoreString.str());
		while(running){
			float deltaTime = clock.getElapsedTime().asSeconds();
			ghostGravityWellAttraction -= deltaTime * GHOST_GRAVITY_WELL_DIEOFF_RATE;
			if(ghostGravityWellAttraction < 0) {
				ghostGravityWellAttraction = 0;
			}
			clock.restart();

			sf::Event event;
			while (screen.pollEvent(event))
			{
				if (event.type == sf::Event::Closed)
				{
					running = false;
				}else
					if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
					{
						running = false;
					}else
						if (event.type == sf::Event::MouseMoved)
						{
							mousePosition = sf::Vector2u(event.mouseMove.x, event.mouseMove.y);
							ghostGravityWellAttraction = 1;
						}else
							if(event.type == sf::Event::MouseButtonPressed){
								if(GameState==STATE_MENU && PlayText.getGlobalBounds().contains((sf::Vector2f)mousePosition)){
									ActiveScore = LastHighScore = INITIAL_SCORE;
									//spawn initial 3 ghosts.
									for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
									//spawn a dude!
									peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), Person_ATex);
									GameState=STATE_PLAYING;
								}
								if (GameState == GameStateGameOver) {
									ActiveScore = INITIAL_SCORE;
									//spawn initial 3 ghosts.
									for(int i=0;i<3;i++) ghostAdd(ghosts, sf::Vector2f(screen.getSize().x*0.5f-20.0f+i*20.0f, screen.getSize().y*0.5f), sf::Vector2f(0.0f, 0.0f), texture, GOOD_MAXIMUM);
									//spawn a dude!
									peopleAdd(people, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)(screen.getSize())), Person_ATex);
									GameState=STATE_PLAYING;

								}
							}
			}
			goto LABELB;
			position+=Velocity;
			if(position.x<0.0f){
				position.x = 0.0f;
				Velocity.x = -Velocity.x;
			}else if(position.x>=(float)(screen.getSize().x-image.getSize().x)){
				position.x = (float)(screen.getSize().x-image.getSize().x);
				Velocity.x = -Velocity.x;
			}
			if(position.y<0.0f){
				position.y = 0.0f;
				Velocity.y = -Velocity.y;
			}else if(position.y>=(float)(screen.getSize().y-image.getSize().y)){
				position.y = (float)(screen.getSize().y-image.getSize().y);
				Velocity.y = -Velocity.y;
			}
			sprite.setPosition(position);  //Good bye old crap.
LABELB:
			allGoodGhosts.clear();
			int goodGhosts = ghostAdvance(ghosts, allGoodGhosts, screen.getSize());
			updateBackground(background, deltaTime, goodGhosts);
			updateBackgroundGhosts(background, deltaTime);
			updateParticles(particles);

			screen.clear();
			drawBackground(screen, background);

			// Ping pong between ghost buffers
			pingPongGhostBuffers(ghostBuffers, sf::Color(255, 255, 255, 0));

			drawBackgroundGhosts(ghostBuffers[currentRenderTarget], background);
			//Let's draw particles here!
			goto LABELW;
LABELX:

			ghostBuffers[currentRenderTarget].display();
			drawTexture(screen, sf::Vector2f(0.0f, 0.0f), ghostBuffers[currentRenderTarget].getTexture());

			drawGhostDropShadows(screen, ghosts);


			goto LABELC;
			screen.draw(sprite);
LABELC:
			//draw people!
			for(size_t i=0;i<people.size();i++){
				float rad = people[i].radius;
				people[i].sprite.setPosition(people[i].position-sf::Vector2f(rad, rad));
				people[i].sprite.setScale((people[i].m_Flag&PERSON_FACE_LEFT)?-1.0f:1.0f, 1.0f);
				screen.draw(people[i].sprite);
			}

			//int GoodIncrement = 0;
			//int BadIncrement = 0;
			for(size_t i=0;i<ghosts.size();i++){
				double rad = ghosts[i].radius;
				ghosts[i].sprite.setPosition(ghosts[i].position-sf::Vector2f(rad, rad));
				ghosts[i].sprite.setColor(sf::Color(GOOD_MAXIMUM-ghosts[i].m_GoodAmnt, 0, ghosts[i].m_GoodAmnt, 25+ghosts[i].m_GoodAmnt * 4 % 231 ));
				screen.draw(ghosts[i].sprite);

				//Do score calculations!
				if(GameState==STATE_PLAYING) ActiveScore+=(ghosts[i].m_GoodAmnt>=GOOD_MINIMUM?GOOD_GHOST_SCORE_VALUE:-BAD_GHOST_SCORE_VALUE)*(ghosts[i].sprite.getScale().x+(ghosts[i].sprite.getScale().x-1.0f)*2.0f);
				else ghosts[i].scaleRate=-ghosts[i].sprite.getScale().x; //destroy all ghosts when in the menu
			}
			HighScore = ActiveScore>HighScore?ActiveScore:HighScore;
			LastHighScore = ActiveScore>LastHighScore?ActiveScore:LastHighScore;
			goto GAMEOVERCHECK;
			if(ActiveScore<=0) GameState=STATE_MENU;
GAMEOVERCHECK:
			if (ActiveScore <= 0) {
				for (int i=0;i<goodGhosts;++i) {
					allGoodGhosts[i]->m_GoodAmnt -= 2.0f*BAD_CONVERSION_RATE;
				}
				ActiveScore = 0;
			}
			if (GameState == GameStatePlaying && goodGhosts <= 0) GameState = GameStateGameOver;


			ScoreString.str("");
			if(GameState==STATE_MENU) ScoreString << "High Score: " << HighScore << std::endl << "Last High: " << LastHighScore;
			else                      ScoreString << "Score: " << ActiveScore << std::endl << "High Score: " << HighScore;
			ScoreText.setString(ScoreString.str());
			goto LABELG;
			if(rand()%50 == 0 || rand() % 60 >= 57) //decreased rate of spawning.
LABELG:
			if(GameState==STATE_MENU){
				if(PlayText.getGlobalBounds().contains((sf::Vector2f)mousePosition)) PlayText.setColor(sf::Color(255, 0, 0));
				else PlayText.setColor(sf::Color(255,255,255));
				screen.draw(PlayText);

			} else if (GameState == GameStateGameOver) {
				gameOverColorFade += 0.02f;
				if (gameOverColorFade >= 1.0f) {
					gameOverColorIndex[0] = gameOverColorIndex[1];
					int count;
					
					while ((gameOverColorIndex[1] = round(randomFloat()*3)) == gameOverColorIndex[0] && count++ < 10);
					gameOverColorFade = 0.0f;
				}
				sf::Color c = fadeColors(gameOverTextColors[gameOverColorIndex[0]], gameOverTextColors[gameOverColorIndex[1]], gameOverColorFade);
				gameOverText.setColor(c);
				screen.draw(gameOverText);

			}else{
				if(SpawnTick==0){
					ghostAdd(ghosts, randomVector(sf::Vector2f(0.0f, 0.0f), (sf::Vector2f)screen.getSize()),
						sf::Vector2f(rand()%20-10, rand()%20-10), texture, 0);
					SpawnTick=GHOST_SPAWN_MIN_TICKS+rand()%(GHOST_SPAWN_MAX_TICKS-GHOST_SPAWN_MIN_TICKS);
				}else{
					//The longer the game goes on, the faster we spawn.
					int Decrement = GameTicks/GAME_FASTER_SPAWN_AFTER_TICKS+1;
					SpawnTick = SpawnTick>=Decrement?SpawnTick-Decrement:0;
				}
			}
			GameTicks++;
			goto LABELY;
LABELW:
			drawParticles(&ghostBuffers[currentRenderTarget], *particles, particleTex);
			goto LABELX;
LABELY:
			screen.draw(ScoreText);

			screen.display();
		}

		if (running) {
			loop(screen, background, position, Velocity, image, sprite, texture, particleTex, Person_ATex, ghosts, people, particles, GameFont, ghostBuffers);
		}
}

#error "Be sure to add resources here!"
see attachment for full file.

also, video:


PARTNERS