Jump to content

  • Log In with Google      Sign In   
  • Create Account


Coding horror experiment in C++

  • You cannot reply to this topic
52 replies to this topic

#41 FuzzyRhombus   Members   -  Reputation: 766

Like
1Likes
Like

Posted 14 November 2013 - 10:02 PM

Not a real update, just changed the sf::Text declarations and commented out GoodIncrement and BadIncrement. This fixed it on my system, hope this helps if anyone else was having trouble too.


#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

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;
	sf::Color color;
	uint lifetime;
};

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.

#define STATE_MENU 0
#define STATE_PLAYING 1

#define PERSON_RADIUS 32.0f
#define PERSON_FACE_LEFT 1

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

#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 sf::Color colorMin, const sf::Color colorMax);

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

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());
}

//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, 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++;
	}

	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);
				addParticles(gParticles, 4, ppos, ppos, pi->position-pi->oldPosition, pj->position-pj->oldPosition, 0.998f, 60, pi->sprite.getColor(), pj->sprite.getColor());
			}
		}

		// 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
	addParticles(gParticles, 10, position, position, sf::Vector2f(-2.0f, -2.0f), sf::Vector2f(2.0f, 2.0f), 0.998f, 100, gh.sprite.getColor(), sf::Color::White);


	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::RenderWindow &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->lifetime--;

		++i;
	}

}

void drawParticles(sf::RenderWindow *screen, std::vector<Particle> &particles, const sf::Texture &texture) {
	for (size_t i=0;i<particles.size();++i) {
		// this could be faster
		drawTexture(*screen, particles[i].position, texture, sf::IntRect(), particles[i].color);
	}
}

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 sf::Color colorMin, const sf::Color colorMax) {
	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;

		// life time is in ticks
		p.lifetime = lifetime;

		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);

		particles->push_back(p);
	}
}

// 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);

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;
	pimage.create(8, 8, pdata);
	particleTex.loadFromImage(pimage);

	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);
}

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) {

		//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;
		bool running = true;
		mousePosition = sf::Vector2u(screen.getSize().x/2, screen.getSize().y/2);

		//Game Text
        static sf::Text ScoreText, PlayText;
        ScoreText.setFont(GameFont);
        PlayText.setFont(GameFont);
        PlayText.setString("Play");
        //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);
		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;
					}
				}
			}
			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:
			int goodGhosts = ghostAdvance(ghosts, screen.getSize());
			updateBackground(background, deltaTime, goodGhosts);
			updateBackgroundGhosts(background, deltaTime);
			updateParticles(particles);

			screen.clear();
			drawBackground(screen, background);
			drawBackgroundGhosts(screen, background);
			//Let's draw particles here!
			goto LABELW;
			LABELX:


			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;
			if(ActiveScore<=0) GameState=STATE_MENU;

			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(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(&screen, *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);
		}
}

#error "Be sure to add resources here!"


Sponsor:

#42 slicer4ever   Crossbones+   -  Reputation: 3480

Like
0Likes
Like

Posted 15 November 2013 - 06:56 AM

yea....forgot to remove the good/bad counters, used them when i was figuring out scoring. msvc apparantly is cool with everything i did, Thanks fuzzy for fixing it.
Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.

#43 FuzzyRhombus   Members   -  Reputation: 766

Like
2Likes
Like

Posted 16 November 2013 - 12:43 PM

yea....forgot to remove the good/bad counters, used them when i was figuring out scoring. msvc apparantly is cool with everything i did, Thanks fuzzy for fixing it.

All good :)

The sf::Text should be fine the way you had it, not sure why I had that problem; but now it works for everybody (I hope).

 

Anyway....

 

 

Finally got some more time to play around with this! Since no one else did anything yet, I just added my changes to this post.

I added a simple game over screen, and a little more conditions to satisfy for dieing, instead of just all of a sudden being back at the menu again lol.

Scoring and death could still use a little work. Seems too easy to me. And there's virtually no way to get a game over without a score of 0.

 

I improved on the particles, added a proper resource, aaaaand since it's ghost themed, added ghost trails! biggrin.png

I only added the effect for particles and background ghosts. Would probably be too much on everything.


#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

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!"


#44 FuzzyRhombus   Members   -  Reputation: 766

Like
1Likes
Like

Posted 16 November 2013 - 12:50 PM

Getting post too long for the resources...

 

So i uploaded the resources as a txt, and the whole file like slicer did.

Attached Files



#45 slicer4ever   Crossbones+   -  Reputation: 3480

Like
0Likes
Like

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:

Attached Files


Edited by slicer4ever, 16 November 2013 - 02:55 PM.

Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.

#46 FuzzyRhombus   Members   -  Reputation: 766

Like
0Likes
Like

Posted 20 November 2013 - 05:34 PM

This seems to have fallen to just you and me slicer (mostly you haha).

 

Anyone else gona add more?



#47 slicer4ever   Crossbones+   -  Reputation: 3480

Like
0Likes
Like

Posted 21 November 2013 - 04:40 PM

This seems to have fallen to just you and me slicer (mostly you haha).
 
Anyone else gona add more?


it seems that way. i'm surprised as their were a few others whom seem interested in the lounge thread, but haven't participated.
Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.

#48 Bacterius   Crossbones+   -  Reputation: 8523

Like
0Likes
Like

Posted 23 November 2013 - 05:09 PM

Well. Looks like it's the end of the road for me. My graphics driver just doesn't appear to be able to handle the awesomeness of the game:

ray@ray ~/gdhorror $ ./main
radeon: The kernel rejected CS, see dmesg for more information.

Might try under Windows later on. FWIW, here's the error log:

[46854.343333] [drm:radeon_cs_parser_relocs] *ERROR* gem object lookup failed 0x16
[46854.343334] [drm:radeon_cs_ioctl] *ERROR* Failed to parse relocation -2!
[46854.343386] [drm:radeon_cs_parser_relocs] *ERROR* gem object lookup failed 0x16
[46854.343387] [drm:radeon_cs_ioctl] *ERROR* Failed to parse relocation -2!
[46854.343456] radeon 0000:01:00.0: evergreen_cs_track_validate_texture:886 mipmap [1] bo too small (layer size 16384, offset 65536, coffset 81920, max layer 1, depth 1, bo size 69632) level0 (128 128 1)
[46854.343458] radeon 0000:01:00.0: evergreen_cs_track_validate_texture:891 problematic surf: (64 64) (2 4 1 1 2 1024 2)
[46854.343458] [drm:radeon_cs_ib_chunk] *ERROR* Invalid command stream !
[46854.359960] radeon 0000:01:00.0: evergreen_cs_track_validate_texture:886 mipmap [1] bo too small (layer size 16384, offset 65536, coffset 81920, max layer 1, depth 1, bo size 69632) level0 (128 128 1)
[46854.359963] radeon 0000:01:00.0: evergreen_cs_track_validate_texture:891 problematic surf: (64 64) (2 4 1 1 2 1024 2)
[46854.359964] [drm:radeon_cs_ib_chunk] *ERROR* Invalid command stream !
[46854.360133] radeon 0000:01:00.0: evergreen_cs_track_validate_texture:886 mipmap [1] bo too small (layer size 1024, offset 65536, coffset 66560, max layer 1, depth 1, bo size 4096) level0 (32 32 1)
[46854.360135] radeon 0000:01:00.0: evergreen_cs_track_validate_texture:891 problematic surf: (16 16) (2 4 1 0 1 4 1)
[46854.360136] [drm:radeon_cs_ib_chunk] *ERROR* Invalid command stream !
[46854.360185] radeon 0000:01:00.0: evergreen_cs_track_validate_texture:835 texture bo too small (layer size 2293760, offset 0, max layer 1, depth 1, bo size 1048576) (896 640)
[46854.360186] [drm:radeon_cs_ib_chunk] *ERROR* Invalid command stream !
[46854.360261] radeon 0000:01:00.0: evergreen_cs_track_validate_texture:835 texture bo too small (layer size 2293760, offset 0, max layer 1, depth 1, bo size 4096) (896 640)
[46854.360262] [drm:radeon_cs_ib_chunk] *ERROR* Invalid command stream !

It's probably just to do with the fact that I don't have hardware acceleration on this box, though I don't know why it worked before, a recent commit must've killed it.


Edited by Bacterius, 23 November 2013 - 05:13 PM.

The slowsort algorithm is a perfect illustration of the multiply and surrender paradigm, which is perhaps the single most important paradigm in the development of reluctant algorithms. The basic multiply and surrender strategy consists in replacing the problem at hand by two or more subproblems, each slightly simpler than the original, and continue multiplying subproblems and subsubproblems recursively in this fashion as long as possible. At some point the subproblems will all become so simple that their solution can no longer be postponed, and we will have to surrender. Experience shows that, in most cases, by the time this point is reached the total work will be substantially higher than what could have been wasted by a more direct approach.

 

- Pessimal Algorithms and Simplexity Analysis


#49 slicer4ever   Crossbones+   -  Reputation: 3480

Like
0Likes
Like

Posted 23 November 2013 - 07:57 PM

might be the font causing the issue.
Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.

#50 tom_mai78101   Members   -  Reputation: 568

Like
0Likes
Like

Posted 26 November 2013 - 02:39 AM

Quick question: Anyone have this stored in a version control system, like Git or SVN? It may be possible that within 2 posts, there may be many additional edits/changes that we may not know of.



#51 FuzzyRhombus   Members   -  Reputation: 766

Like
0Likes
Like

Posted 27 November 2013 - 12:23 PM

Quick question: Anyone have this stored in a version control system, like Git or SVN? It may be possible that within 2 posts, there may be many additional edits/changes that we may not know of.

https://github.com/mjbshaw/GameDev.net-Collaborative-Coding-Horror-2013/tree/master

 

It hasn't been updated recently though... sad.png

 

Are you talking about splitting the code and resources in two?



#52 tom_mai78101   Members   -  Reputation: 568

Like
0Likes
Like

Posted 27 November 2013 - 08:29 PM

That's a possibility, but I haven't thought that far yet. I'm just curious if there's a version control system, that's all.



#53 rip-off   Moderators   -  Reputation: 8114

Like
0Likes
Like

Posted 01 December 2013 - 02:57 PM

Thanks everyone, I'm closing the experiment. As noted after the jump, all this really means is that I'm unpinning the topics, by all means continue to contribute!


Edited by rip-off, 01 December 2013 - 02:58 PM.






PARTNERS