• Create Account

# Servant of the Lord

Member Since 24 Sep 2005
Offline Last Active Today, 12:35 AM

### #5107465How to put objects and enemies in a 2d level?

Posted by on 06 November 2013 - 10:21 AM

So what you are saying is that I get each ring's x and y position like this?

rings[n]->x - mapxoff;
rings[n]->y - mapyoff;

Hmm  I cant seem to visualize it
My screen is 640*480

I wanna draw a ring at say coordinate 100, 100;
so 100 - maxoff?

Yep. If a coin is at 100, and the camera is at 120, what is supposed to happen? The coin is 20 units to the left of the camera.
coin(100) - camera(120) = -20. Drawing a coin at -20, is drawing the coin 20 units to the left of the camera. It does what is intended.

If the coin is at 200, and the camera is at 120, what is supposed to happen? The coin is 80 units to the right of the camera.
coin(200) - camera(120) = 80. Drawing a coin at 80 is drawing the coin 80 units to the right of the camera. It works correctly, giving negative positions for objects to the left of the camera, and positive positions for objects to the right of the camera, which draw onscreen exactly as desired.

It's important that you do (objectPos - cameraPos) and not (cameraPos - objectPos) or it'd give the wrong results.

All your objects need to be stored with their global position on the map, but drawn with their local position. It's easiest, fast, and mentally makes sense one you comprehend it.

servant, if you don't mind, can you give me a light code example using my rings objects?

The exact same as what you already have, just subtract the camera position from any object in the game world.

```void drawRings(int cameraX, int cameraY)
{
//loop through all ring object
for(int n = 0; n < RINGS; ++n)
{
//If the rings have not been collected yet
if(rings[n]->alive)
{
//Animate each ring
if(++rings[n]->framecount > rings[n]->framedelay)
{
if(++rings[n]->curframe > rings[n]->maxframe)
rings[n]->curframe = 0;

rings[n]->framecount = 0;
}

//now draw each ring to the buffer
draw_sprite(buffer, ring_images[rings[n]->curframe], (rings[n]->x - cameraX), (rings[n]->y - cameraY));
}
}
}```

Your code was already pretty much correct, it was just that camera subtracting that it needed.

### #5107359How does one get started with c++?

Posted by on 05 November 2013 - 11:44 PM

I suggest getting two books: A "fun" book you can read on a couch/bed and flip through, and a "serious" book that goes more indepth lesson-by-lesson while infront of a computer. Then supplement that with googling, reading articles, and asking questions on the forums.

If you're going to start learning C++ now, note that C++ just released a major new update (C++11), and has a minor update on it's way (C++14). With any books, tutorials, articles, or videos, you should try to focus on the newer stuff, because the recommended ways of using C++ has changed. C++ is still C++, but there are different recommended overall styles of coding that has been refined over the past decade and a half, and it'd be good to start off doing things the "Right Way" from the start.

This isn't absolutely critical, as the new ways will proliferate and you'll absorb it later anyway, but it is especially important if you decide to order some books. I can't offer any specific recommendations, but look for those published after 2010 - especially those that directly mention C++11.

There are some really good older books that have held up fantastically, but they are usually the more abstract architectural or development-focused, rather than "learn the language"-focused books that you'd be looking for.

### #5107238How to put objects and enemies in a 2d level?

Posted by on 05 November 2013 - 02:01 PM

Okay so I made a level using a 2d map editor. Now when I get to the code I can make the world scroll relative to my characters position. So now I decide to code in a few object (coins, rings etc). I set their x and y position and find out they move along with my charcter rather than being in their own spots around the level. Okay, so I made one huge backbuffer that is the size of the level it self. Blit the level onto it, than the object as well. Than I blit that backbuffer to my normal buffer(which is the size of my screen) where my character is and move and blit relative to my characters position. That seems to fix the problem, but now im experiencing slow downs. Is there a better way to do this?

Sounds like your camera code is wrong.

All objects, including the player, should have a position in "global coordinates". Global coordinates are the coordinates from some fixed location in the loaded area (which might be the center of the area, or the upper left corner, or something like that).

Screen coordinates are relative to the location of the camera (the upper-left corner of the screen).

The camera itself has a global coordinate (i.e. it's at location (x,y) in the area).

You calculate screen coordinates by subtracting the camera position from the global coordinate of the object, and use this to draw.

```screenPosOfObject = (myObject.globalPos - myCamera.globalPos);
draw(myObject, screenPosOfObject);```

Keep positions in global positions, and only convert them to screen positions on-the-fly when you need them - it won't slow you down.

Don't use the buffer idea; as you found out, that'd burn through your framerate faster than napalm.

### #5106604SFML and Tiled Map Editor

Posted by on 02 November 2013 - 10:08 PM

When you have a project: Your project has .cpp files and .h files. Your project also links to .dll files and .a files and #includes  .h files of other projects / libraries.

This part of C++, where you get other projects to interact with your own, can be confusing and take alot of patience and trial-and-error, so no, it's not a stupid question, but it can be a hassle you'll have to fight through by perseverance. Every project I want my code to work with is slightly different, and figuring out how to compile them or make them play nice with my code is always a little bit of a hassle. You can download precompiled versions... but those can be hassles also, for a dozen different reasons.

Because of this, you cannot be given a three, five, or even ten-step tutorial that will universally work. It'd be more like a giant flowchart of "Is your project X? Are you trying to use Y? Are you compiling with Z? Do you have Q enabled? Does the library also have Q enabled? Do you want to use it as N or as M? Did the project..." and so on. It always takes trail and error, and ain't fun, but you'll get used to it eventually.

Sorry for not being able to give you a pleasant answer!  It's my least-favorite part of programming.

But programming in general is fun, so don't get discouraged by the unfun parts!

Also, this specific bit of hassle becomes less of a pain once you become familiar with how to work through the problems as they arise.

Probably the easiest option, in this one specific case, for this one specific circumstance, is to copy the library's .cpp files that are in the 'src' folder (only the ones in the 'src' folder, not the .cpp files outside of it), into your own project's .cpp files, and copy the project's .h files that are in the 'include' folder and paste those with your own .h files, and then tell your specific IDE, in whatever specific way your IDE does it, to count those .cpp files and those .h files as part of your project.

That's part A, which may have all kinds of compile issues and stuff that you'll need to work through in a manner completely unique to your specific situation.

Part B would be linking to zlib, which is a different set of ifs, whens, and maybes, and a different set of potential compiler errors and unique setup that differs from person to person.

So I guess back to the first question: Does your project already compile fine and run fine using just SFML, without loading maps?

Posted by on 02 November 2013 - 09:24 PM

Copyrights are automatic. Anything you create is automatically yours: Art, Code, Architecture, Clothing design, House design, Music, Graffiti, Photographs (for example, of nature), Writing, and alot more besides. Even forum posts. You own the post you just made. But you gave GameDev.net permission to share it with others by the nature of your agreement with GameDev.net (depending on the Terms of Service, you might've given them ownership of the post, but I haven't read their terms of service).

Just because it's yours doesn't mean people won't steal it anyway.
But because it's yours companies in the United States and other 1st world non-Chinese nations won't risk getting sued.
Other companies in other countries you can't do anything about, regardless of what legal precautions you take.

Perhaps you mean "licensing"? Licensing is a way to allow others to use your copyrights as long as they follow certain conditions. Licensing is basically a contract permitting others to use what you own.

I like to say, 'copyright is implicit in creation'. The second you create it, it's copyrighted. Automaticly.
If you used someone else's work and modified it to make your work, then you only have a copyright on the changes made, but they still own the original work, and your work is a 'derivative work' of their work - and unless you have permission to use their original work, then you can't use your derived work (but neither can they, because you still own the changed parts).

Works are copyrighted whether they have a message attached to them or not, and regardless of whether they have a name written on them or not. If I paint a picture, I don't have to write on the back of it, "SotL ownz this workz - 2013". It's copyrighted whether I say it is or not. Only if I explicitly release ownership of the copyright into the public domain, or if the copyright expires (What is it currently? My entire life plus 80 more years? Something stupid like that), only then is it no longer copyrighted.

But again, just because it is copyrighted doesn't mean some random kid online won't copyright it. It only means it's illegal for them to (civil law, not criminal law, afaik).

Copyrights are designed for the benefit of the creators and, indirectly, the public.

Patents are designed for the benefit of inventors to permit sharing of technology so everyone benefits and civilization advances. It benefits the public indirectly, but majorly.

Trademarks are designed directly for the benefit of the public, but can be beneficial to companies as well.

All are man-made ideas that are relatively recent in history (within the past 400 years), and that some nations ignore.

Copyrights and Patents can be abused; Copyrights by being way too long, and patents by some of the issued patents being too vague or too obvious.

But overall the ideas of all three are great ideas that benefit everyone in the long-term, except for the cases where they are abused.

Leastwise, that's my opinion.

### #5106399Coding horror experiment in C++

Posted by on 02 November 2013 - 02:08 AM

Awesome artwork, riuthamus - Segmented was looking forward to that sprite.
```#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <vector>
#include <cmath>
#include <stdint.h>
#include <iostream>

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

uint32_t rgba;
Channel channel;
};

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

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

{
sf::Sprite sprite;
float maxVisibility;
};

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

};

extern const ImageData imageData;

#define PLAYER_GHOST 0
#define GHOST_GOOD 1
#define CONVERSION_DISTANCE 80.0f
#define GOOD_MINIMUM 100
#define GOOD_MAXIMUM 255
#define GOOD_CONVERSION_RATE 2

static sf::Vector2u mousePosition;

#define MASS 2 * 1e-2

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

//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,
{
//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.
}

//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)
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;
p->oldPosition.x = p->position.x;
}
p->oldPosition.x = p->position.x;
}

//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;
//do conversion if within distance.
if(a<=CONVERSION_DISTANCE*CONVERSION_DISTANCE){
if((vec[i].m_GoodAmnt>=GOOD_MINIMUM && vec[j].m_GoodAmnt<GOOD_MINIMUM)){ //i is good, j is bad
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;
}else if(vec[i].m_GoodAmnt<GOOD_MINIMUM){ //both i and j are bad.
}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:;
}
}

// convert to bigger "good" ghost
for(size_t i=0;i<vec.size();i++){
for(size_t j=i+1;j<vec.size();j++){
if (vec[i].m_GoodAmnt == GOOD_MAXIMUM && vec[i].m_GoodAmnt == GOOD_MAXIMUM && GoodGhosts > 4)
{
if (vec[i].sprite.getScale().x >= 3.0f) break;

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

if (distanceBetweenX + distanceBetweenY < 50.0f)
{
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[j] = vec[vec.size() - 1];
vec.pop_back();
GoodGhosts--;
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.m_GoodAmnt = GoodAmnt;
gh.sprite.setTexture(textureBall);
gh.sprite.setColor(sf::Color((int)position.x%256,(int)position.y%256,rand()%256,200));

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

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

for(int i = 0; i < numShadowGhosts; ++i)
{
shadowGhost.maxVisibility = (randomFloat() * 0.35f) + 0.1f;

}
}

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

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

//If out of bounds (towards the lower-right of the screen)...
|| 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.
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)
{
}
}

{
sf::Vector2f ghostOffset(5.0f, 7.0f);//5.0f,5.0f);

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

// forward declaration
void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
sf::Texture &texture, std::vector<Ghost> &ghosts);

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 ImageData *iconImage = &imageData;
screen.setIcon(iconImage->width, iconImage->height, iconImage->pixel_data);

sf::Image image, imageBall;
image.create(imageData.width, imageData.height, imageData.pixel_data);

sf::Texture texture;
texture.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);

goto LABELA;
sprite.setTexture(texture);
sprite.setPosition(position);
LABELA:
std::vector<Ghost> ghosts;
//spawn inital 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);

loop(screen, background, position, Velocity, image, sprite, texture, ghosts);
}

void loop(sf::RenderWindow &screen, Background &background, sf::Vector2f &position, sf::Vector2f &Velocity, sf::Image &image, sf::Sprite &sprite,
sf::Texture &texture, std::vector<Ghost> &ghosts) {

//don't want to thrash the stack with the tail recursion
static sf::Clock clock;

bool running = true;
mousePosition = sf::Vector2u(screen.getSize().x/2, screen.getSize().y/2);

{
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:
updateBackground(background, deltaTime, goodGhosts);
updateBackgroundGhosts(background, deltaTime);

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

goto LABELC;
screen.draw(sprite);
LABELC:
for(size_t i=0;i<ghosts.size();i++){
ghosts[i].sprite.setColor(sf::Color(GOOD_MAXIMUM-ghosts[i].m_GoodAmnt, 0, ghosts[i].m_GoodAmnt, ghosts[i].m_GoodAmnt * 4 % 256 ));
screen.draw(ghosts[i].sprite);
}

if(rand()%50 == 0 || rand() % 60 >= 57) //decreased rate of spawning.
sf::Vector2f(rand()%20-10, rand()%20-10), texture, 0);

screen.display();
}

if (running) {
loop(screen, background, position, Velocity, image, sprite, texture, ghosts);
}
}

const ImageData 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",
};

```

Best commit comment ever.

### #5104647Place to find amateur/hobbyist graphical artists for my game.

Posted by on 26 October 2013 - 03:27 PM

I agree that you should try not to 'exploit' anyone, but if you're making a game that's non-commercial or open-source then I don't see a problem with recruiting artists to work for free. Since the thread title says, "amateur/hobbyist", I'm assuming that's the case.

I'd suggest starting with a mix of making your own art, and using free stock art (see OpenClipArt.org and OpenGameArt.org for starters), with the understanding that most of it would only be placeholder artwork. It can look really poor, as long as it functions well enough to continue letting you get programming done.

Once your game is in a playable and functional state, and you've personally already invested six or more months of your time into it, then show it on places like where artists tend to gather. Some of those places are for-hire-for-money, others have artists who are willing to pitch in and help out for free if your game will be released for free.

The reason why your game should be in a playable functional state and that you should've already invested alot of your own time into it, is so you are less likely to ruin other people's investments into your game (which now become partly their game also), by getting bored and cancelling the project. Just common courtesy. It also means they are more willing to jump in and help out if they can see that some things are already working.

And having poor placeholder artwork won't demotivate artists. Infact, it might encourage them, because almost anything they make will be better than that, so they might be excited to leap in and get crackin' on the project. Just remember that if they are working for free, than in becomes their project also, not just yours, so be open to hearing their opinions. And also remember that if they are working for free, they aren't employees, so don't try to be their boss and order them around. Though you do need to have an idea in advance of what you are wanting, and your goals for the project, so the project isn't just flopping mindlessly around and energy isn't being wasted developing art and code and content that will eventually end up being replaced and wasted.

### #5103248How can I avoid exposing thirdparty types in my API classes?

Posted by on 21 October 2013 - 04:38 PM

Pimpl what you can, forward-declare what you can't (i.e. things in function signatures).

I don't bother Pimpling every class, but some of the more commonly used and larger classes get Pimpl'd.

I Pimpl like this:

MyClass.h
```#include "Common/Assorted/Pimpl.h"

class MyClass
{
public:
//...stuff...

private:
private:
struct Impl;
Pimpl<Impl> pImpl;
};
```
MyClass.cpp
```#include "Common/Assorted/Pimpl_Impl.h"

struct MyClass::Impl
{
Impl(const std::string &str);
std::string stuff;
int blah = 357;
};

//A constructor for the impl is completely optional.
MyClass::Impl::Impl(const std::string &str)
{
stuff = str;
}

MyClass::MyClass() : pImpl("Test")
{
std::cout << pImpl->stuff << std::endl;
}
```
Pimpl.h
```#ifndef COMMON_ASSORTED_PIMPL_H
#define COMMON_ASSORTED_PIMPL_H

/*
This file provides the declaration of the Pimpl class,
and should only be #included by the .h file of the class being Pimpl'd.

The Pimpl_Impl.h class should be #included by the .cpp file of the class being Pimpl'd.
*/

template<typename Type>
class Pimpl
{
public:
//Default constructor.
Pimpl();
//Multi-argument constructor.
template<typename ...Args>
Pimpl(Args &&...);

//Copy constructor.
Pimpl(const Pimpl &other);
//Copy-assignment operator.
Pimpl &operator=(const Pimpl&);

//Move constructor.
Pimpl(Pimpl &&other);
//Move-assignment operator.
Pimpl &operator=(Pimpl&&);

//Destructor.
~Pimpl();

//Non-const access:
Type *operator->();
Type *operator*();

//Const access:
const Type *operator->() const;
const Type *operator*() const;

private:
//The pointer to the implementation of the class being Pimpl'd.
Type *data = nullptr;
};

#endif // COMMON_ASSORTED_PIMPL_H
```
Pimpl_Impl.h
```#ifndef COMMON_ASSORTED_PIMPL_IMPLEMENTATION_H
#define COMMON_ASSORTED_PIMPL_IMPLEMENTATION_H

/*
This file provides the implementation of the Pimpl class,
and should only be #included by the .cpp file of the class being Pimpl'd.
*/

#include "Common/Assorted/Pimpl.h"
#include <utility>

//Default constructor.
template<typename Type>
Pimpl<Type>::Pimpl()
{
this->data = new Type;
}

//Multi-argument constructor.
template<typename Type>
template<typename ...Args>
Pimpl<Type>::Pimpl(Args && ...args)
{
this->data = new Type(std::forward<Args>(args)...);
}

//Copy constructor.
template<typename Type>
Pimpl<Type>::Pimpl(const Pimpl &other)
{
this->data = new Type(*(other.data));
}

//Copy-assignment operator.
template<typename Type>
Pimpl<Type> &Pimpl<Type>::operator=(const Pimpl &other)
{
if(this != &other)
{
Type *temp = new Type(*(other.data));
std::swap(this->data, temp);
delete temp;
}

return *this;
}

//Move constructor.
template<typename Type>
Pimpl<Type>::Pimpl(Pimpl &&other)
{
//Swap the pointers so this class gets the old data pointer, and 'other' gets the null pointer.
std::swap(this->data, other.data);
}

//Move-assignment operator.
template<typename Type>
Pimpl<Type> &Pimpl<Type>::operator=(Pimpl &&other)
{
//Swap the pointers so this class gets the old data pointer, and 'other' gets the null pointer.
std::swap(this->data, other.data);
return *this;
}

//Destructor.
template<typename Type>
Pimpl<Type>::~Pimpl()
{
delete this->data;
}

//Non-const access:
template<typename Type>
Type *Pimpl<Type>::operator->()
{
return this->data;
}

template<typename Type>
Type *Pimpl<Type>::operator*()
{
return this->data;
}

//Const access:
template<typename Type>
const Type *Pimpl<Type>::operator->() const
{
return this->data;
}

template<typename Type>
const Type *Pimpl<Type>::operator*() const
{
return this->data;
}

#endif //COMMON_ASSORTED_PIMPL_IMPLEMENTATION_H
```
The 'Pimpl' class is a reusable and consistent tool to Pimpl my classes. It manages the data pointer for you, so RAII, but at the same time is compact and small enough to save the (presumed, on my part) compile overhead of #including <memory> for unique_ptr, which (in GCC) includes a bunch of other headers that include other headers.

### #5102721I'm a beginner who wants to create something, but not sure how..

Posted by on 19 October 2013 - 03:46 PM

The initial foray into programming is boring, but it gets more and more enjoyable after the first few months. At least, for me it was that way.

The problem with what you were trying to do is that League of Legends is a complex game... and not open for modification. You'd have to use a complex and weird hack to implement what you wanted, because you don't have access to League of Legend's source code. That hack might even be accidentally detected as some kind of cheat and get you banned from the game.

In programming, sometimes the things that seem easy are actually alot more difficult than they appear. Sometimes the things that seem hard are actually easier than you think,

It's easier to make Pong from scratch than to modify a game that you don't have the source code to.

Programming definitely takes work, and reading is definitely involved, but it gets more exciting if you stick with it for the long-haul.

If you really want to just "jump in" to something, find a smaller game with publicly available source code. Like maybe Battle for Wesnoth - though I haven't personally browsed Wesnoth's source code, so I'm not sure how legible it is.

Personally, I prefer the books + tutorials (not video tutorials; ugh!) way myself, but different people have different learning styles.

I wouldn't consider, "Don't read, just play", the best way toward learning a skillset though. That would just encourage me to shy away from difficult work and only play around with the fun parts. That wouldn't help me grow in skill, because I wouldn't be challenged by difficulties when those difficulties get boring and I move on to something else.

Have you tried GameMaker? It requires actual use of logic, but you can see things happening on-screen right from the beginning, and it is very flexible and powerful. You can then gradually learn the scripting language to further expand your knowledge, but in incremental steps, if doing it the boring way (studying books) isn't an option on the table.

### #5102517so i took one look at the sdl source code...

Posted by on 18 October 2013 - 05:28 PM

Libraries like that are grown over time - someone didn't set out to code specifically what now exists, but it has grown from version to version, and with each new platform that gets supported.

If you come from a C++ background, have a look at the SFML source code - created mostly by a single person much more recently in history.

Also, what exactly do you mean by "that type of code"? Are you impressed by the number of lines or files? If so, that's not a good measurements for determining the quality of the code.

Because SDL is written in the C programming language, if you use C++ you shouldn't try to mimic the style of the C code, because C++ has different coding styles and recommended guidelines for quality code.

Posted by on 16 October 2013 - 05:19 PM

Just saw this post on the front page of Stack Overflow, and thought it funny...

I didn't know that Google made a contact-lens versions of Google Glass, or that they have an API for forcing it to eject from your eye!

(The actual thread, which is much less interesting that what my mind first conceived)

### #5100237How to code game data

Posted by on 10 October 2013 - 11:33 AM

A player's inventory could be as simple as: std::vector<YourItemClass>

### #5099999A better character creation system?

Posted by on 09 October 2013 - 02:52 PM

In French (supposedly; I don't speak it myself), almost every object is either female or male.

In English, gender for inanimate objects are much less common.

"It" to refer to a person feels forced. A singular "They" feels less forced, but still clumsy.

Why is gender agnostic a desirable feature? It feels like it takes away options, rather than offering more.

I like ShaneC's idea of a introvert/extrovert setting. It should even be a bar with several notches for varying degrees.

Posted by on 09 October 2013 - 01:10 PM

If you're too obvious about helping players, it might come off as condescending or annoying.

In New Super Mario Bros Wii, if you die on a level too many times (more than eight in a row), it makes an annoying noise and a green box appears to break. Breaking it makes Luigi appear, and he runs a ghost of one of the game's developers showing you how to get through the level.

My complaints with it were:

1) The noise was annoying, and alerted everyone else in the living room that I died eight or more times on the level.

2) Almost every time it appeared, it was because I was dying while trying to accomplish a super-hard-bonus-task, not while trying to make it through the level normally, so

It was like Clippy from Microsoft Word appearing onscreen and saying, "Hi! I see you suck at this game and are dying too much. Want me to show you how to get though the level?", when my goal wasn't trying to get through the level, but trying to get a specific hard Yoshi Coin on that level. This occurred many times, since I was 100-percenting the game.

This tutorial system is a good idea, but the game failed to tell when you were dying because the level was too difficult for you, or dying because you were getting all the bonus coins that were meant to be challenging.

### #5099814Should i use a linked list for this (C++)?

Posted by on 08 October 2013 - 09:19 PM

I agree with ApochPiQ: If the order of your elements don't matter, use a vector and swap-and-pop.

ApochPiQ, what about the fact that I'm going to add to the list at any time?  I don't see a performance hit with the list, but with the vector I'll hit the resize & copy routines regularly.

First, if you're using C++11, you'd hit the resize and move your elements regularly (make sure your move-constructors are labeled noexcept, or you will in-fact copy). Second, your elements are pointers (so a move vs a copy isn't any different). Copying a range of pointers is as fast as copying a range of integers. It's a single memcpy() for the entire vector of pointers - very fast.

You can reserve() the amount of memory you're likely to need in advance, but even if you fail to reserve() you'll likely rarely need many actual reallocations.

Swapping and popping is very very fast also - no reallocation required. When you later push_back() a new element, you still won't need to reallocate, because your previous 'pop' (from the swap-and-pop) didn't reallocate, and so still has the not-yet-filled capacity.

I like having a SwapAndPop() templated function that I can pass a lambda to:

```#include <iostream>
#include <algorithm> //For std::swap
#include <memory> //For std::unique_ptr
#include <vector>

//std::make_unique implementation (it was forgotten in the C++11 standard, and will be added later).
//Once it's added, I can just remove this from here.
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

//Swaps and pops every element in 'container', for which the callback function 'predicate(element)' returns true.
//This is faster than std::remove_if(), but does not preserve the order of the elements like 'remove_if()' does.
template<typename ContainerType, typename FunctionType>
void SwapAndPop(ContainerType &container, FunctionType predicate)
{
for(typename ContainerType::iterator it = container.begin(); it != container.end();)
{
if(predicate(*it))
{
//Swap the value of the current element with the element at the back of the container.
std::swap(*it, container.back());
//Pop the back of the container.
container.pop_back();

if(container.empty())
{
break;
}
}
else
{
++it;
}
}
}

class Object
{
static unsigned nextID;

public:
Object() : timeToDelete(++nextID % 3), id(nextID) { }

bool timeToDelete = false;
size_t id = 0;

public:
typedef std::unique_ptr<Object> uPtr;
};

unsigned Object::nextID = 0;

int main()
{
const size_t NumObjectsForTest = 40;

std::vector<Object::uPtr> objects;

//Create all the objects.
for(size_t i = 0; i < NumObjectsForTest; ++i)
{
objects.push_back(make_unique<Object>());
}

//Print all the objects.
for(const auto &object : objects)
{
std::cout << "Object " << object->id << ": " << (object->timeToDelete? "[Time to delete]":"[Still alive]") << std::endl;
}

std::cout << "------------------------------------\n"
<< "Calling SwapAndPop...\n"
<< "------------------------------------\n";

SwapAndPop(objects, [](Object::uPtr &objectPtr) -> bool { return objectPtr->timeToDelete; });

//Print all the objects again.
for(const auto &object : objects)
{
std::cout << "Object " << object->id << ": " << (object->timeToDelete? "[Time to delete]":"[Still alive]") << std::endl;
}

return 0;
}
```

If you're likely to add/erase alot of objects of the exact same type (and if you find that this area of code is actually a bottleneck), you might even want to just 'swap', but leave the pointer and the memory hanging around so you can re-use it without the overhead of another call to 'new'.

PARTNERS