Ganoosh

Members
  • Content count

    30
  • Joined

  • Last visited

Community Reputation

774 Good

About Ganoosh

  • Rank
    Member
  1. Same issue here. There is an extra "form_email" param sent with the payload that seems to be hardcoded to "danielle.griffin@informa.com"... tried changing that to my email as well, but no difference. Empty 200 response and no emails. Maybe that will help with investigation?
  2. I actually just wrote a blog post about this. Simply put, HTML5 is definitely legit, but write HTML5 games for that purpose. Intend them to run in browser. Don't try to replace an otherwise native app or try to make the next CoD in JS. I'm mainly a C++ guy, but I wanted to give it a shot, so I'm currently writing a small JS game with pixi.js. I'm impressed, but it's definitely different.   Don't do this. The performance of UIWebView is not the same as the browser. Chrome for Android is amazing though.   It sounds like your attempts haven't been very recent. Even in just the past 6 months HTML5 support has grown. It is just as much capable, if not more, than Flash now, and it's going to continue to grow. I reccomend playing around with all those languages regardless, though!    IE has always been a problem to web developers in general. I honestly wouldn't even worry about it. Anyone using IE9 (or IE at all) probably isn't looking to play web games, and if they are, they should upgrade. That is like supporting iOS1 when releasing iOS games.     I forgot about AIR and Stage3D. I've always been an advocate of "Flash is here to stay," but I'm on the other side now. You bring up good points, but Flash in browser is definitely on the way to retirement. If you're new to either at this point, and trying to decide between HTML5 and Flash, I vote HTML5. 
  3. Getting started with Node.JS part 1: Setup

    Nice article. I'm interested in Socket.IO as well, so I look forward to the next article! One note though: by default terminal control sequences still use CTRL on OSX, so it's no different there. :)
  4. This came just in time! Been playing with JS the past few days for the first time in years, so I'm trying to figure out the best way to handle about basic tasks and such. Some no-brainers here (if you understand GC), but also some catches. All very helpful in the end. I love how you related it to individual engines and explained what they're doing with your code.
  5. It was fun! Would definitely try to contribute more if there's another one.  As for why I didn't contribute more (I wanted to do more than I did), the biggest issue was I personally didn't have enough time (I would assume similar for others as well). I know that's not what you wanted to hear, but it also ties in with any "structural" problems I noticed. If I had infinite time and less other priorites, I would've done way more regardless.   I mostly agree with swiftcoder, see my comments below.   Not to call you out slicer, but your large commits were part of the reason I didn't do more later on. They were great! =D Just too much at once. There were some others as well, but towards the end you were doing most of the commits (which were rather large lol) with my adding some effects. I didn't have much time to put into it as I would've liked, and anytime I checked back it was a huge change. More to absorb and think about, rather than just playing for a few minutes and making some small updates.  Although I guess this would be just as much of a problem for someone only checking every few days or once a week.      I think the specific framing of the competition discouraged me from contributing more than trivially:   - Managing the source code via the forum was a tremendous hassle compared to using git, and it just wasn't worth going through. In particular, making a change, refreshing the page, and discovering that you needed to manually rebase your changes on someone else's was just untenable. Anyone on this forum should be able to use/learn git, and I don't think we should be ignoring the right tools for this sort of thing.   - The competition was pitched more as a coding horror than as an effort to develop a complete game, so I was caught off guard when people started taking it seriously.   - The rules favoured very small incremental changes, and I didn't see a path to adding features that way. Major changes seemed against the spirit of the competition, so I didn't add any features in the end.   I didn't really have a problem with the forum commits, and someone did start a repo (though it wasn't really maintained). I wouldn't have a problem with git being a must for the next one though.   As for the horror aspect, I think the horror was more supposed to be the mashup of code snippets, not the game itself. Either way it was stil fun!    Going back to the commit size, I think smaller commits should be more enforced. Anytime I'd check with an idea of something to add, when I had time to later to do it someone had added it already. I was going to do a surprise physics update near the beginning but I was beat to it. Then I wasn't sure what to do next, and my ideas would get behind. I was going to add text support before that update was rolled out lol. I thought to add these things because they were small and quick, but essential systems. All the while, each commit adding these features would change gameplay as well. I ended up mainly just adding effects systems that weren't there yet. I think it should be limited to adding a single feature or small amounts of changes. I'm not picking any names this time  but a lot of updates would add some subsystem as well as update gameplay, change some previous functionality etc. Just made it harder to keep up with in the time I had. I feel if commits are more limited, even with more activity, less will change with time. This would obviously take longer to complete something playable and fun, but I think it would give more chance for people to contribute what they can. Plus more contributers with small changes + different coding styles = lots more horror! =]   Also, with larger updates, a lot of gameplay is more the result of one person's idea. This only allows further building on it, and that can only be done so much for any game, really. You also have to "adjust" to that thinking to come with further good ideas as well. Not that this is necessarily bad, but if more people contributed smaller gameplay elements, I think it would be able to evolve more with less effort from each contributor.   It was fun though, and everyone did an awesome job! 
  6. Coding horror experiment in C++

    https://github.com/mjbshaw/GameDev.net-Collaborative-Coding-Horror-2013/tree/master   It hasn't been updated recently though...    Are you talking about splitting the code and resources in two?
  7. 10 Ways To Improve Your Indie Game Development

    This is a very nice summary!  A demo is never "wrong." It's called a demo for a reason. If the demo is revealing too much as you say, the game probably isn't very interesting in the first place.
  8. Coding horror experiment in C++

    This seems to have fallen to just you and me slicer (mostly you haha).   Anyone else gona add more?
  9. Coding horror experiment in C++

    Getting post too long for the resources...   So i uploaded the resources as a txt, and the whole file like slicer did.
  10. Coding horror experiment in C++

    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!  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!"
  11. Coding horror experiment in C++

    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!"
  12. Coding horror experiment in C++

    When I try to compile your update, I get this: main.cpp: In function ‘void loop(sf::RenderWindow&, Background&, sf::Vector2f&, sf::Vector2f&, sf::Image&, sf::Sprite&, sf::Texture&, sf::Texture&, sf::Texture&, std::vector<Ghost, std::allocator<Ghost> >&, std::vector<People, std::allocator<People> >&, std::vector<Particle, std::allocator<Particle> >*, sf::Font&)’: main.cpp:810: error: jump to label ‘LABELW’ main.cpp:751: error: from here main.cpp:770: error: crosses initialization of ‘int BadIncrement’ main.cpp:769: error: crosses initialization of ‘int GoodIncrement’   If I comment out the BadInc, GoodInc lines, it compiles fine. However when I run it crashes immediately with this: ghost(81396,0x7fff763b3180) malloc: *** error for object 0x1057b7320: pointer being freed was not allocated *** set a breakpoint in malloc_error_break to debug Abort trap: 6 On osx 10.8, compiling with llvm gcc 4.2   For some reason the sf::Text constructors used were crashing on my system. Just declaring the vars as default and explicity setting the string and font works fine though. Strange lol. I uploaded the changed version just in case this caused a problem for anyone else.
  13. Coding horror experiment in C++

    That looks awesome!   I will finally get around to my promised update soon. I was thinking of adding text support as well; good thing I didn't yet!    I can probably get some help adding some sounds or music this week though =]
  14. Coding horror experiment in C++

      Well, at the time I was thinking it was just the code tags that were too long, but I guess I misunderstood. Perhaps just keep track of the resources in first post and only repost those if changes are necessary?   Ah, perhaps you're right. That's even better idea then haha   Sounds good. I'll just keep adding effects until then 
  15. Coding horror experiment in C++

    ^^    Simple fix   I think that's what Dragonsoulj implied, which I will +1;   Going to try and commit sometime soon. If I'm the first from now I'm going to adopt this convention if that's ok