• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

Ganoosh

Members
  • Content count

    29
  • Joined

  • Last visited

Community Reputation

774 Good

About Ganoosh

  • Rank
    Member
  1. 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. 
  2. 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. :)
  3. 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.
  4. 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! 
  5. 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?
  6. 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.
  7. This seems to have fallen to just you and me slicer (mostly you haha).   Anyone else gona add more?
  8. Getting post too long for the resources...   So i uploaded the resources as a txt, and the whole file like slicer did.
  9. 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!"
  10. 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!"
  11. 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.
  12. 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 =]
  13.   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 
  14. ^^    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
  15. Finally contributing here haha. Small, hasty update. Also added some pointer confusion to throw off all the reference-domination hehe   Everything's better with particles! #include <SFML/System.hpp> #include <SFML/Window.hpp> #include <SFML/Graphics.hpp> #include <vector> #include <cmath> #include <stdint.h> #include <iostream> 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; #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 5 #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 PERSON_RADIUS 32.0f #define PERSON_FACE_LEFT 1 static sf::Vector2u mousePosition; static std::vector<Particle> *gParticles; // yay global reference #define MASS 2 * 1e-2 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); 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); 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)); 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; //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); loop(screen, background, position, Velocity, image, sprite, texture, PersonTex, particleTex, ghosts, people, &particles); } 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) { //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); bool running = true; mousePosition = sf::Vector2u(screen.getSize().x/2, screen.getSize().y/2); while(running){ float deltaTime = clock.getElapsedTime().asSeconds(); clock.restart(); sf::Event event; while (screen.pollEvent(event)) { if (event.type == sf::Event::Closed) { running = false; } if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)) { running = false; } if (event.type == sf::Event::MouseMoved) { mousePosition = sf::Vector2u(event.mouseMove.x, event.mouseMove.y); } } 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); 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); } 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); } goto LABELG; if(rand()%50 == 0 || rand() % 60 >= 57) //decreased rate of spawning. LABELG: 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 SpawnTick--; drawParticles(&screen, *particles, particleTex); screen.display(); } if (running) { loop(screen, background, position, Velocity, image, sprite, texture, particleTex, Person_ATex, ghosts, people, particles); } } const ImageData32 imageData = { 32, 32, "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0" "\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0" "\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0" "\0\377\0\224\377\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377" "\0\0\0\377\0\224\377\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0" "\0\0\377\0\224\377\377\0\224\377\377\0\224\377\377\0\0\0\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\0\0\0\377\0\224\377\377\0\224\377\377\0\224\377\377\0\0\0\377" "\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\0\0\0\377\0\0\0\377\0\224\377\377\0\224\377\377\0\224\377" "\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\0\0\0\377\0\224\377\377\0\224\377\377" "\0\224\377\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\224\377\377" "\0\224\377\377\0\224\377\377\0\0\0\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0" "\224\377\377\0\224\377\377\0\224\377\377\0\0\0\377\0\0\0\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\0\0\0\377\0\224\377\377\0\224\377\377\0\224\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\0\224\377\377\0\224\377" "\377\0\224\377\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377" "\377\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0" "\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0" "\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0" "\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\0\0\0\377", }; const ImageData64 Person_A = { 64, 64, "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\341\255\377\377\2642\377\377\2758\377\377\2642\377\377\2747\377\377\277" "9\377\377\2642\377\377\320D\377\377\321E\377\377\321E\377\377\321E\377\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\2642\377" "\377\2642\377\350\242'\377\364\2551\377\337\232#\377\361\2521\377\345\237" "&\377\355\2500\377\332\227!\377\351\2450\377\330\225\40\377\351\2450\377" "\377\321E\377\377\321E\377\377\321E\377\377\321E\377\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\2642\377\377\2642\377\355\2500\377" "\352\2450\377\377\2642\377\377\302;\377\376\2631\377\364\2664\377\353\245" ")\377\375\2747\377\377\2747\377\377\306>\377\377\321E\377\377\321E\377\351" "\2450\377\332\230\"\377\352\2460\377\330\225\40\377\377\321E\377\377\321" "E\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\2642\377\343\235%\377\332\227!\377\377\2642\377" "\377\2642\377\364\254-\377\342\237'\377\332\230\"\377\337\235'\377\335\234" "$\377\337\237&\377\352\2471\377\377\320E\377\377\321E\377\377\321E\377\377" "\321E\377\377\317C\377\377\316C\377\363\2748\377\363\2708\377\332\227!\377" "\377\321E\377\377\321E\377\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\271\271\271\377\271\271\271\377\271\271\271\377\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\330\225\40\377\342\235%\377\377\2642\377\377\2642\377\377\2642\377" "\331\226!\377\340\236'\377\340\241'\377\375\315C\377\377\321E\377\377\320" "D\377\377\317C\377\366\301;\377\366\275;\377\353\2601\377\356\2564\377\342" "\243)\377\377\320D\377\377\321E\377\377\317C\377\377\316C\377\365\277:\377" "\375\312A\377\377\2674\377\330\225\40\377rss\377rss\377rss\377\230\231\230" "\377\271\271\271\377\271\271\271\377\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\265w\25\377\354\245)\377\331" "\226\40\377\377\2642\377\330\225\40\377\351\2450\377\331\227!\377\377\267" "4\377\377\317C\377\377\302<\377\377\313A\377\377\306>\377\377\305>\377\377" "\316C\377\377\314B\377\377\315B\377\377\315B\377\377\316C\377\374\307?\377" "\356\2654\377\353\2501\377\377\317C\377\377\311@\377\377\313A\377\357\261" "2\377\342\235%\377\330\225\40\377YYY\377rss\377\230\231\230\377\271\271\271" "\377\271\271\271\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\312\211\34\377\305\204\33\377\330\225\40\377" "\330\225\40\377\352\2460\377\377\2642\377\377\2642\377\377\2642\377\377\264" "2\377\377\321E\377\377\2642\377\377\2642\377\375\2621\377\376\2704\377\377" "\2716\377\377\301:\377\377\310>\377\377\315B\377\377\315B\377\377\315B\377" "\371\305=\377\351\2450\377\376\317D\377\360\254.\377\345\242(\377\320\216" "\35\377\264v\25\377===\377YYY\377YYY\377\230\231\230\377\271\271\271\377" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\264v\25" "\377\264v\25\377\325\223\37\377\264v\25\377\375\2631\377\377\2642\377\376" "\2632\377\377\2642\377\377\2642\377\377\2642\377\377\2642\377\377\2642\377" "\377\2642\377\377\315C\377\377\2642\377\377\2705\377\376\2642\377\376\266" "3\377\374\304<\377\374\310?\377\375\311?\377\370\301:\377\363\2716\377\342" "\236%\377\342\235%\377\273~\27\377\253p\22\377\350\2634\377\360\2675\377" "\334\232#\377===\377YYY\377\230\231\230\377\271\271\271\377\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\256r\23\377\300\200\30\377\264v\25" "\377\326\224\40\377\327\225\40\377\330\225\40\377\377\2642\377\377\2642\377" "\377\2642\377\377\2642\377\377\2642\377\377\2642\377\377\2642\377\377\264" "2\377\377\2642\377\377\2642\377\377\2642\377\377\2642\377\357\255.\377\355" "\254.\377\353\252,\377\357\257/\377\353\250+\377\333\230#\377\264w\25\377" "\320\230'\377\374\310?\377\377\315B\377\377\315B\377\377\316B\377\340\240" "'\377===\377YYY\377\230\231\230\377\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\254p\22\377\242i\17\377\253o\21\377\275}\27\377\302\202\31\377\325\222\37" "\377\355\246*\377\327\224\37\377\327\224\37\377\364\253-\377\325\222\37\377" "\324\222\37\377\324\221\36\377\350\241'\377\343\235%\377\346\240&\377\347" "\240'\377\344\236&\377\377\2674\377\345\241'\377\345\240&\377\335\231#\377" "\336\232#\377\314\213\35\377\272|\26\377\301\206\35\377\376\313A\377\377" "\314A\377\377\312@\377\377\314A\377\377\316C\377\377\300:\377\330\225\40" "\377YYY\377\230\231\230\377\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\242i\17" "\377\243j\17\377\242i\17\377\252o\22\377\261v\24\377\266y\26\377\312\211" "\33\377\271{\26\377\316\215\35\377\317\215\35\377\314\213\34\377\316\215" "\35\377\321\216\35\377\320\216\35\377\320\216\35\377\320\216\35\377\317\216" "\35\377\300\202\31\377\272}\27\377\265y\25\377\304\205\33\377\274~\30\377" "\253p\22\377\263v\25\377\327\237*\377\376\313A\377\377\314A\377\377\310?" "\377\377\307?\377\377\306>\377\377\312@\377\377\317C\377\330\225\40\377Y" "YY\377\230\231\230\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\264v\25\377\242i\17\377" "\242i\17\377\242i\17\377\242i\17\377\246k\20\377\252o\22\377\246l\20\377" "\245k\17\377\251o\22\377\250m\21\377\244k\20\377\246k\21\377\247m\20\377" "\252o\21\377\251o\21\377\247m\20\377\252p\22\377\244k\17\377\245l\21\377" "\260s\23\377\262u\24\377\312\220\"\377\363\2737\377\374\303<\377\375\312" "@\377\377\314A\377\377\305<\377\377\305=\377\377\2779\377\377\2653\377\351" "\251,\377\377\2726\377\330\225\40\377===\377YYY\377\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\264v\25\377" "\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377" "\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377" "\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377" "\264v\25\377\266x\26\377\327\224\40\377\332\227!\377\363\2664\377\377\304" "<\377\377\302;\377\377\2779\377\377\2664\377\377\2715\377\376\2674\377\372" "\2600\377\343\236%\377\330\225\40\377\264v\25\377\330\225\40\377===\377=" "==\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\264v\25\377\330\225\40\377\330\225\40\377\330\225\40\377\330\225\40\377" "\330\225\40\377\330\225\40\377\330\225\40\377\330\225\40\377\330\225\40\377" "\331\226!\377\330\225\40\377\330\225\40\377\333\227!\377\334\231\"\377\336" "\232#\377\343\236%\377\346\240'\377\354\245)\377\357\250+\377\365\254-\377" "\367\256.\377\377\2705\377\377\2705\377\374\2621\377\376\2631\377\377\264" "2\377\377\2642\377\377\2642\377\371\257/\377\345\237&\377\332\227!\377\264" "v\25\377\242i\17\377\242i\17\377\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\264v\25\377\376\2632\377\330\225\40\377\377\2642\377\376\2642\377\331\226" "!\377\377\2642\377\377\2642\377\375\2631\377\373\2611\377\375\2631\377\377" "\2642\377\377\2642\377\377\2642\377\377\2642\377\377\2642\377\376\2631\377" "\371\2600\377\365\254.\377\367\255/\377\367\256/\377\366\255/\377\366\255" "/\377\366\255/\377\366\255/\377\371\2570\377\371\2570\377\353\244*\377\330" "\225\40\377\330\225\40\377\264v\25\377\242i\17\377\242i\17\377\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\264v\25\377\331" "\226!\377\331\226!\377\326\223\37\377\351\242(\377\330\225\40\377\330\225" "\40\377\330\225\40\377\330\225\40\377\377\2642\377\330\225\40\377\330\225" "\40\377\376\2632\377\330\225\40\377\377\2642\377\330\225\40\377\377\2642" "\377\376\2631\377\331\226!\377\333\230\"\377\337\233$\377\361\251-\377\364" "\253/\377\360\250,\377\337\233#\377\335\231#\377\335\231#\377\334\230\"\377" "\264v\25\377\242i\17\377\242i\17\377\271tN\377\271tN\377\322\221m\377\335" "\237}\377\350\255\214\377\364\274\235\377\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\242i\17\377\265w\25" "\377\272|\27\377\266x\26\377\266x\26\377\277\177\30\377\277\200\31\377\276" "~\30\377\267y\26\377\267y\26\377\266x\26\377\267y\26\377\272{\27\377\274" "~\30\377\275~\30\377\276\177\30\377\302\202\32\377\305\205\32\377\313\212" "\34\377\306\206\33\377\334\230$\377\333\227#\377\302\202\32\377\264v\25\377" "\264v\25\377\330\225\40\377\264v\25\377\242i\17\377\242i\17\377\271tN\377" "\277{V\377\322\221m\377\322\221m\377\322\221m\377\352\257\217\377\362\271" "\232\377\364\274\235\377\364\274\235\377\364\274\235\377\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\242i\17\377\264v\25\377\264v\25\377" "\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377" "\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377\264v\25\377" "\267x\26\377\272{\27\377\273|\30\377\270y\26\377\265v\25\377\264v\25\377" "\264v\25\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377" "\377\377\377\377\271tN\377\322\221m\377\322\221m\377\322\221m\377\362\271" "\232\377\364\274\235\377\355\307\262\377\355\307\262\377\355\307\262\377" "\364\274\235\377\364\274\235\377\322\221m\377\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\242i\17\377\242i\17\377\242i\17\377\242i\17" "\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17" "\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17" "\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\242i\17\377\271tN\377" "\271tN\377\271tN\377\271tN\377\377\377\377\377===\377\322\221m\377\322\221" "m\377\341\244\202\377\363\272\233\377\364\274\235\377\364\274\235\377\355" "\307\262\377\355\307\262\377\355\307\262\377\355\307\262\377\364\274\235" "\377\322\221m\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\322\221m\377\271tN\377\271tN\377" "\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271" "tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN" "\377\322\221m\377\322\221m\377\322\221m\377\271tN\377===\377===\377\322\221" "m\377\334\235{\377\364\274\235\377\364\274\235\377\364\274\235\377\360\302" "\251\377\355\307\262\377\355\307\262\377\355\307\262\377\355\307\262\377" "\364\274\235\377\322\221m\377\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\322\221m\377\322\221" "m\377\322\221m\377\322\221m\377\316\214h\377\271tN\377\322\221m\377\322\221" "m\377\322\221m\377\271tN\377\272uO\377\324\223o\377\322\221m\377\322\221" "m\377\322\221m\377\326\226s\377\333\235z\377\337\242\177\377\342\246\204" "\377\342\246\204\377\322\221m\377\271tN\377===\377===\377\322\221m\377\356" "\265\225\377\364\274\235\377\364\274\235\377\364\274\235\377\363\275\237" "\377\362\277\243\377\357\304\255\377\355\307\262\377\364\274\235\377\364" "\274\235\377\322\221m\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\322\221m\377\342\246\204" "\377\342\246\204\377\342\246\204\377\321\221n\377\271tN\377\322\221m\377" "\343\247\205\377\317\217l\377\342\246\204\377\300|W\377\342\246\204\377\346" "\253\212\377\342\246\204\377\342\247\205\377\342\246\204\377\350\255\214" "\377\342\246\204\377\364\274\235\377\364\274\235\377\364\274\235\377\322" "\221m\377\271tN\377===\377\322\221m\377\347\254\213\377\364\274\235\377\364" "\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235" "\377\364\274\235\377\364\274\235\377\364\274\235\377\322\221m\377\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\322\221m\377\342\246\204\377\342\246\204\377\347\255\213" "\377\332\234z\377\271tN\377\322\221m\377\317\217k\377\351\256\216\377\364" "\274\235\377\355\263\223\377\364\274\235\377\362\271\232\377\357\266\226" "\377\355\264\224\377\354\263\222\377\360\267\230\377\364\274\235\377\364" "\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\322\221m\377" "\322\221m\377\342\245\204\377\347\254\213\377\364\274\235\377\364\274\235" "\377\355\307\262\377\364\274\235\377\364\274\235\377\364\274\235\377\364" "\274\235\377\364\274\235\377\364\274\235\377\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\322\221m\377\342\246\204\377\342\246\204\377\354\263\222\377\345" "\251\211\377\271tN\377\311\206b\377\344\250\207\377\360\303\252\377\364\274" "\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377" "\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274" "\235\377\364\274\235\377\364\274\235\377\364\274\235\377\354\263\222\377" "\347\254\213\377\335\237|\377\334\236{\377\357\265\225\377\364\274\235\377" "\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274" "\235\377\342\246\204\377\322\221m\377\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\322\221m\377\342\246\204\377\342\246\204\377\354\262\222\377\353\261\221" "\377\303\200[\377\271tN\377\303\177Z\377\320\217k\377\357\304\254\377\357" "\304\255\377\356\305\257\377\322\222n\377\356\264\225\377\364\274\235\377" "\364\274\235\377\364\274\235\377\363\275\237\377\362\277\243\377\360\303" "\252\377\364\274\235\377\364\274\235\377\353\261\221\377\342\246\204\377" "\327\227t\377\325\225q\377\326\226s\377\353\261\221\377\356\264\224\377\351" "\256\215\377\342\245\204\377\342\246\204\377\342\246\204\377\322\221m\377" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\327\230" "u\377\342\246\204\377\351\255\215\377\364\274\235\377\323\224q\377\311\210" "d\377\271tN\377\271tN\377\317\215i\377\321\220l\377\310\206a\377\303\200" "[\377\307\205a\377\364\274\235\377\364\274\235\377\361\300\245\377\356\305" "\256\377\355\307\262\377\355\307\262\377\364\274\235\377\364\274\235\377" "\364\273\234\377\342\246\204\377\333\235{\377\315\213g\377\320\216j\377\323" "\222n\377\322\221m\377\323\222n\377\333\235z\377\322\221m\377\322\221m\377" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\322\221m\377\342\246\204\377\343\247\205\377\363\271\232\377\362\271" "\232\377\337\243\201\377\307\205`\377\303\200[\377\271tN\377\274xR\377\310" "\206a\377\331\233x\377\364\274\235\377\364\274\235\377\355\307\262\377\355" "\307\262\377\355\307\262\377\355\307\262\377\355\307\262\377\364\274\235" "\377\364\274\235\377\364\274\235\377\342\246\204\377\342\246\204\377\311" "\210c\377\300|W\377\276zT\377\276zU\377\300|W\377\304\201\\\377\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\324\224q\377\342\246\204\377\347\254" "\212\377\357\266\226\377\361\271\231\377\360\267\227\377\343\247\206\377" "\327\230u\377\362\272\233\377\364\274\235\377\364\274\235\377\364\274\235" "\377\364\274\235\377\364\274\235\377\355\307\262\377\364\274\235\377\364" "\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235" "\377\351\256\215\377\342\246\204\377\336\240~\377\316\215i\377\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\322\221m\377\342\246\204\377\342\246\204\377\343\250" "\206\377\360\267\227\377\364\274\235\377\364\274\235\377\364\274\235\377" "\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274" "\235\377\364\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377" "\364\274\235\377\364\274\235\377\364\274\235\377\352\260\217\377\343\247" "\205\377\342\246\204\377\326\226s\377\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\324\223o\377\342\246\204\377\342\246\204\377\342" "\246\204\377\347\254\212\377\356\264\224\377\361\270\230\377\360\270\231" "\377\363\273\234\377\364\274\235\377\364\274\235\377\364\274\235\377\364" "\274\235\377\364\274\235\377\364\274\235\377\364\274\235\377\363\273\234" "\377\351\256\215\377\345\251\210\377\342\246\204\377\342\246\204\377\342" "\246\204\377\322\221m\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\324\223p\377\337\242\177\377\342\246\204\377\342" "\246\204\377\342\246\204\377\342\246\204\377\342\246\204\377\342\246\204" "\377\342\246\204\377\342\246\204\377\346\253\211\377\345\252\210\377\345" "\251\210\377\345\251\210\377\345\252\210\377\343\247\205\377\343\247\205" "\377\342\246\204\377\342\246\204\377\330\230u\377\322\221m\377\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\322\221n\377\331\233x\377\340\243\201\377" "\340\244\202\377\341\245\203\377\341\245\203\377\337\242\200\377\342\246" "\204\377\342\246\204\377\342\246\204\377\342\246\204\377\342\246\204\377" "\342\246\204\377\337\241\177\377\333\235z\377\330\231v\377\323\222o\377\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\271tN\377\277{V\377\303\201\\\377\276" "zT\377\276zU\377\326\226s\377\325\225q\377\326\226r\377\325\225r\377\322" "\222n\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\202\236-\377\202\236-\377\202\236-\377\271tN\377\271tN\377\271tN\377\322" "\221m\377\271tN\377\364\274\235\377\364\274\235\377_v\30\377\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377\202\236-\377\222" "\264,\377\202\236-\377\202\236-\377_v\30\377_v\30\377_v\30\377_v\30\377\322" "\221m\377\322\221m\377\255\322=\377_v\30\377\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\202\236-\377\255\322=\377\255\322=\377\255\322=\377\222\264,\377" "\222\264,\377\202\236-\377\202\236-\377\202\236-\377_v\30\377\24.F\377\35" "Be\377\255\322=\377\255\322=\377_v\30\377\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377\255\322" "=\377\255\322=\377\255\322=\377\255\322=\377\255\322=\377\202\236-\377\222" "\264,\377\202\236-\377\202\236-\377_v\30\377\24.F\377\35Be\377\202\236-\377" "\255\322=\377_v\30\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\202\236-\377\255\322=\377\255\322=\377\255\322=\377" "\255\322=\377\222\264,\377\255\322=\377\222\264,\377\222\264,\377\202\236" "-\377\202\236-\377\202\236-\377_v\30\377\24.F\377\35Be\377\255\322=\377_" "v\30\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\202\236-\377\255\322=\377\255\322=\377\255\322=\377\255\322=\377\255" "\322=\377\222\264,\377\202\236-\377\202\236-\377\202\236-\377\202\236-\377" "\202\236-\377_v\30\377_v\30\377\35Be\377\202\236-\377\222\264,\377_v\30\377" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377\255\322=\377\255" "\322=\377\255\322=\377\255\322=\377\222\264,\377\222\264,\377\202\236-\377" "\222\264,\377\202\236-\377\222\264,\377\202\236-\377\202\236-\377\202\236" "-\377_v\30\377\24.F\377\35Be\377\222\264,\377_v\30\377\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\202\236-\377\255\322=\377\255\322=\377\255\322=\377\222\264,\377" "\255\322=\377\222\264,\377\222\264,\377\222\264,\377\202\236-\377\202\236" "-\377\202\236-\377\202\236-\377_v\30\377\202\236-\377_v\30\377\24.F\377\35" "Be\377\202\236-\377_v\30\377\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377\255" "\322=\377\255\322=\377\255\322=\377\255\322=\377\222\264,\377\222\264,\377" "\202\236-\377\222\264,\377\202\236-\377\202\236-\377\202\236-\377\202\236" "-\377_v\30\377\202\236-\377_v\30\377\24.F\377\24.F\377\202\236-\3770=\11" "\377_v\30\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\202\236-\377\255\322=\377\255\322=\377\222\264" ",\377\255\322=\377\222\264,\377\222\264,\377\222\264,\377\202\236-\377\222" "\264,\377\202\236-\377\202\236-\377\202\236-\3770=\11\377_v\30\377_v\30\377" "\24.F\377\35Be\377\202\236-\3770=\11\377_v\30\377\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377" "\222\264,\377\222\264,\377\222\264,\377\222\264,\377\202\236-\377\202\236" "-\377\202\236-\377\222\264,\377\202\236-\377\202\236-\377\202\236-\377\202" "\236-\3770=\11\377_v\30\377_v\30\377\24.F\377\24.F\377\202\236-\3770=\11" "\377_v\30\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\202\236-\377\222\264,\377\222" "\264,\377\222\264,\377\222\264,\377\202\236-\377\222\264,\377\202\236-\377" "\202\236-\377\202\236-\377\202\236-\377\202\236-\3770=\11\377_v\30\377_v" "\30\377\24.F\377\35Be\377\202\236-\377\322\221m\377\322\221m\377\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\202\236-\377\202\236-\377\202\236-\377\202\236-\377" "\202\236-\377\202\236-\377\202\236-\377\202\236-\377\202\236-\377\202\236" "-\377\202\236-\377\202\236-\3770=\11\3770=\11\377_v\30\377\24.F\377\24.F" "\377\202\236-\377\364\274\235\377\342\246\204\377\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377" "\271tN\377\271tN\377\271tN\377\271tN\377\271tN\377\326\226s\3770=\11\377" "0=\11\377\24.F\377\35Be\377_v\30\377\364\274\235\377\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\322\221m\377\322\221m\377\322\221m\377\322\221m\377" "\322\221m\377\322\221m\377\322\221m\377\322\221m\377\322\221m\377\364\274" "\235\377\364\274\235\377\342\246\204\377\322\221m\377\12\35/\377\12\35/\377" "\24.F\377\24.F\377\12\35/\377\342\246\204\377\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\322\221m\377\322\221m\377\326\226s\377\342\246\204\377\342" "\246\204\377\353\261\221\377\364\274\235\377\364\274\235\377\364\274\235" "\377\364\274\235\377\342\246\204\377\322\221m\377\322\221m\377\12\35/\377" "\12\35/\377\367\332\31\377\315\267#\377\12\35/\377\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\322\221m\377\322\221m\377" "\322\221m\377\271tN\377\353\261\221\377\353\261\221\377\364\274\235\377\364" "\274\235\377\355\307\262\377\342\246\204\377\271tN\377\322\221m\377\12\35" "/\377\12\35/\377\315\267#\377\266\241\21\377\12\35/\377\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\322\221" "m\377\322\221m\377\271tN\377\342\246\204\377\342\246\204\377\353\261\221" "\377\364\274\235\377\355\307\262\377\355\307\262\377\342\246\204\377\12\35" "/\377\12\35/\377\12\35/\377\12\35/\377\12\35/\377\12\35/\377\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\326\226s\377\322\221m\377\271tN\377\353\261\221\377\342\246" "\204\377\353\261\221\377\364\274\235\377\364\274\235\377\342\246\204\377" "\12\35/\377\12\35/\377\35Be\377\35Be\377\24.F\377\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\12\35/\377\322\221m\377\353\261" "\221\377\326\226s\377\326\226s\377\342\246\204\377\24.F\377\35Be\377\35B" "e\377\35Be\377\35Be\377\24.F\377\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\12\35/\377\12\35/\377\12\35/\377\24.F\377\35" "Be\377\24.F\377\35Be\377\24.F\377\35Be\377\24.F\377\24.F\377B*\16\377}Y0" "\377\265\207R\377\265\207R\377\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\24.F\377\35Be\377\24.F\377\35" "Be\377\24.F\377\24.F\377\35Be\377\35Be\377\24.F\377\24.F\377B*\16\377Y;\30" "\377}Y0\377\241r=\377\241r=\377\265\207R\377\265\207R\377\265\207R\377\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\24.F\377\35Be\377\24" ".F\377\35Be\377\35Be\377\35Be\377\24.F\377\24.F\377B*\16\377B*\16\377}Y0" "\377\241r=\377\241r=\377\241r=\377\241r=\377\241r=\377\241r=\377\265\207" "R\377\265\207R\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\24.F\377\24" ".F\377\24.F\377\35Be\377\24.F\377B*\16\377B*\16\377B*\16\377}Y0\377}Y0\377" "\241r=\377}Y0\377\241r=\377}Y0\377\241r=\377}Y0\377}Y0\377\241r=\377}Y0\377" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\24.F\377\24.F\377B*\16\377B*\16" "\377B*\16\377Y;\30\377Y;\30\377Y;\30\377iG\37\377Y;\30\377iG\37\377Y;\30" "\377iG\37\377Y;\30\377iG\37\377Y;\30\377iG\37\377iG\37\377iG\37\377iG\37" "\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0B*\16\377B*\16\377Y;\30\377iG\37\377iG" "\37\377}Y0\377iG\37\377iG\37\377iG\37\377iG\37\377iG\37\377}Y0\377}Y0\377" "iG\37\377}Y0\377}Y0\377iG\37\377}Y0\377}Y0\377iG\37\377\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0Y;\30\377Y;\30\377Y;\30\377Y;\30\377Y;\30\377Y;\30\377Y;\30\377" "Y;\30\377Y;\30\377Y;\30\377iG\37\377Y;\30\377Y;\30\377iG\37\377iG\37\377" "Y;\30\377Y;\30\377iG\37\377Y;\30\377Y;\30\377\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0", }; Just added a simple emitter-less particle system. Plan on expanding it a bit later. Unless someone else does first