I'm trying to make a program that randomly generates a user-defined number of circles on the screen (using SFML), but when I choose a number of circles above 6, I get the Vector Subscript Out of Range error. Any number = to or below 6 works as expected.
I've tried looking up the error message, but none of the answers i've seen apply to my code. The code breaks at the first for loop, but if I comment out the first loop, it breaks at the second loop.
Here is my code:
#include "SFML/Graphics.hpp"
#include <stdlib.h>
#include <iostream>
int main()
{
srand(time(NULL));
const int WINDOW_X = 800;
const int WINDOW_Y = 480;
sf::RenderWindow window(sf::VideoMode(WINDOW_X, WINDOW_Y), "Epidemic Simulation", sf::Style::Close | sf::Style::Titlebar);
int numPeople = 10;
float size = 5;
int status = 0;
std::vector<sf::CircleShape> person(size);
for (int i = 0; i < numPeople; ++i)
{
if (status == 0)
person[i].setFillColor(sf::Color::Green);
else if (status == 1)
person[i].setFillColor(sf::Color::Red);
else if (status == 2)
person[i].setFillColor(sf::Color::Black);
else
{
std::cout << ("Error: Incorrect color value");
person[i].setFillColor(sf::Color::Green);
}
person[i].setFillColor(sf::Color::Green);
}
for (int i = 0; i < numPeople; ++i)
{
int xPos = rand() % WINDOW_X - (size * 2);
int yPos = rand() % WINDOW_Y - (size * 2);
if (xPos < (size * 2))
xPos = 0;
if (yPos < (size * 2))
yPos = 0;
std::cout << ("X position: ") << xPos << (", Y position: ") << yPos << "\n";
person[i].setPosition(xPos, yPos);
person[i].setRadius(size);
}
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear(sf::Color::White);
for (int i = 0; i < numPeople; ++i)
window.draw(person[i]);
window.display();
}
return 0;
}
Because you initiate person(size) with size = 5 and the loop is going up to numPeople = 10. You probably wanted to write:
std::vector<sf::CircleShape> person(numPeople);
Related
I have been working on a simple C++ and SFML program recently, but have gotten stuck. Basically I want to do two things:
I want to generate a number of circles with random coordinates
I want to make those circles move randomly around the screen
I figured using a vector for the circles would be best so that I can use am int to determine the number of shapes.
The coordinates are generating correctly, but the shape is not drawing to the screen!
Here is my code:
#include "SFML/Graphics.hpp"
#include <stdlib.h>
#include <iostream>
int main()
{
srand(time(NULL));
const int WINDOW_X = 800;
const int WINDOW_Y = 480;
sf::RenderWindow window(sf::VideoMode(WINDOW_X, WINDOW_Y), "Epidemic Simulation", sf::Style::Close | sf::Style::Titlebar);
int numPeople = 2;
float size = 5;
int status = 0;
//Declare CircleShape
std::vector<sf::CircleShape> person(size);
//Change color depending on status
for (int i = 0; i < numPeople; i++)
{
if (status == 0)
person[i].setFillColor(sf::Color::Green);
else if (status == 1)
person[i].setFillColor(sf::Color::Red);
else if (status == 2)
person[i].setFillColor(sf::Color::Black);
else
{
std::cout << ("Error: Incorrect color value");
person[i].setFillColor(sf::Color::Green);
}
}
//Generate random coordinates for each circle
for (int i = 0; i < numPeople; i++)
{
int xPos = rand() % WINDOW_X - (size * 2);
int yPos = rand() % WINDOW_Y - (size * 2);
if (xPos < (size * 2))
xPos = 0;
if (yPos < (size * 2))
yPos = 0;
std::cout << ("X position: ") << xPos << (", Y position: ") << yPos << "\n";
}
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear(sf::Color::White);
//Draw circle
for (int i = 0; i < numPeople; i++)
window.draw(person[i]);
window.display();
}
return 0;
}
Any idea why the shape is not drawing? And how would I get the shape to move in a random direction?
It seems you just have to make a few changes.
The main ones (from the output of the diff command) are:
> // Give the circles definite radius value and segment count:
> for (int i = 0; i < numPeople; i++)
> {
> person[i].setRadius(size);
> person[i].setPointCount(100);
> }
and also:
// Generate random coordinates for each circle:
for (int i = 0; i < numPeople; i++)
{
int xPos = rand() % WINDOW_X - (size * 2);
int yPos = rand() % WINDOW_Y - (size * 2);
... <clip> ...
person[i].setPosition(xPos, yPos);
}
Side note:
The srand() and rand() functions are part of a legacy C API. They are not meant to be used in new C++ code. It is recommended to #include the <random> header and use the C++11 API. See paper for details: n3551.pdf.
I started Learning C++ yesterday And In that time i was rewriting my java "Falling Sand" Sandbox Game code in C++ using SFML (bit simplified since i don't know C++). but Performance in C++ was much worse in than java, what could be the reason for it, I Know this is very unfocused question, but my code is simple, i probably have a newbie mistakes which should be easy to correct.
#include <SFML/Graphics.hpp>
#include <iostream>
sf::Clock sclock;
const int WIDTH = 1440, HEIGHT = 960;
const char Blank = 0, Sand = 1, Water = 2;
const char* title = "Sandbox Simulation";
char map[WIDTH*HEIGHT];
sf::Vector2i mousePos;
int dist(int x1, int x2, int y1, int y2) {
return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));
}
int localBrushSize = 48;
short halfBrush = (short)floor(localBrushSize / 2);
char chosen = Sand;
void place() {
int randY = 0;
int randX = 0;
randX = randY = 1;
for (int y = mousePos.y - halfBrush; y <= mousePos.y + halfBrush; y += randY) {
for (int x = mousePos.x - halfBrush; x <= mousePos.x + halfBrush; x += randX) {
int I = x + y * WIDTH;
int distance = dist(mousePos.x, x, mousePos.y, y);
if (distance < halfBrush && I > 0) {
map[I] = chosen;
}
}
}
}
float Delta_Time() {
return sclock.restart().asSeconds();
}
int main() {
map[11111] = 2;
sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), title);
sf::Event evnt;
sf::RectangleShape pixel(sf::Vector2f(1.0f, 1.0f));
window.clear();
while (window.isOpen()) {
while (window.pollEvent(evnt)) {
switch (evnt.type) {
case sf::Event::Closed:
window.close();
break;
}
}
if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
mousePos = sf::Mouse::getPosition(window);
place();
}
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
int I = x + y * WIDTH;
switch (map[I]) {
case Sand:
pixel.setPosition(x, y);
pixel.setFillColor(sf::Color::Yellow);
window.draw(pixel);
break;
case Water:
pixel.setPosition(x, y);
pixel.setFillColor(sf::Color::Cyan);
window.draw(pixel);
break;
}
}
}
window.display();
}
return 0;
}
You might be able to make a cached / "framebuffer" like this
TOTALLY untested concept code. WIDTH/HEIGHT might be mixed up, endianess is not OK, etc.
sf::Image image;
sf:Image.create(WIDTH, HEIGHT, sf::Color(0, 0, 0));
sf::Sprite sprite;
std::array<sf::Uint8, WIDTH * HEIGHT * 4> pixels; // you can reuse this. The 4 is the size of RGBA
...
for(int y = 0; y < HEIGHT; y++) {
for(int x = 0; x < WIDTH; x++) {
int offset = (x + y * WIDTH) * 4;
pixels[offset] = sf::Color::Yellow.toInteger(); // in case BIG/Litte endian confusion you might have to do the below.
//pixels[offset + 0 ] = 255; // R?
//pixels[offset + 1 ] = 255; // G?
//pixels[offset + 2 ] = 255; // B?
//pixels[offset + 3 ] = 255; // A?
}
}
image.LoadFromPixels(WIDTH, HEIGHT, pixels);
sprite.SetImage(image);
window.Draw(sprite);
window.Display();
so recently I have been wanting to make a snake game in C++ using SFML in Microsoft Visual studio 2015 and I made one and I am actually pretty satisfied with my work but there is a problem, that I forgot to make a game over for it and it seems like I couldn't make it work and it really had me on edge. So I thought I could use stack overflow's help. I would really appreciate it if you guys would let me know how to make it work and please keep it simple obvious.
Here is my code:
// GraphicalLoopSnakeGame.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <ctime>
#include <SFML/Graphics.hpp>
using namespace sf;
int N = 30, M = 20;
int size = 16;
int w = size * N;
int h = size * M;
int dir, num = 4;
struct Snake {
int x, y;
} s[100];
struct Fruit {
int x, y;
} f;
void Tick() {
for(int i = num; i > 0; --i) {
s[i].x = s[i - 1].x;
s[i].y = s[i - 1].y;
}
if(dir == 0) s[0].y += 1;
if(dir == 1) s[0].x -= 1;
if(dir == 2) s[0].x += 1;
if(dir == 3) s[0].y -= 1;
if((s[0].x == f.x) && (s[0].y == f.y)) {
num++;
f.x = rand() % N;
f.y = rand() % M;
}
if(s[0].x > N) s[0].x = 0;
if(s[0].x < 0) s[0].x = N;
if(s[0].y > M) s[0].y = 0;
if(s[0].y < 0) s[0].y = M;
for(int i = 1; i < num; i++)
if(s[0].x == s[i].x && s[0].y == s[i].y) num = i;
}
int main() {
srand(time(0));
RenderWindow window(VideoMode(w, h), "Snake Game!");
Texture t1, t2, t3;
t1.loadFromFile("images/white.png");
t2.loadFromFile("images/red.png");
t3.loadFromFile("images/green.png");
Sprite sprite1(t1);
Sprite sprite2(t2);
Sprite sprite3(t3);
Clock clock;
float timer = 0, delay = 0.13;
f.x = 10;
f.y = 10;
while(window.isOpen()) {
float time = clock.getElapsedTime().asSeconds();
clock.restart();
timer += time;
Event e;
while(window.pollEvent(e)) {
if(e.type == Event::Closed) window.close();
}
if(Keyboard::isKeyPressed(Keyboard::Left)) dir = 1;
if(Keyboard::isKeyPressed(Keyboard::Right)) dir = 2;
if(Keyboard::isKeyPressed(Keyboard::Up)) dir = 3;
if(Keyboard::isKeyPressed(Keyboard::Down)) dir = 0;
if(Keyboard::isKeyPressed(Keyboard::W)) dir = 3;
if(Keyboard::isKeyPressed(Keyboard::D)) dir = 2;
if(Keyboard::isKeyPressed(Keyboard::A)) dir = 1;
if(Keyboard::isKeyPressed(Keyboard::S)) dir = 0;
if(timer > delay) {
timer = 0;
Tick();
}
////// draw ///////
window.clear();
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++) {
sprite1.setPosition(i * size, j * size);
window.draw(sprite1);
}
for(int i = 0; i < num; i++) {
sprite2.setPosition(s[i].x * size, s[i].y * size);
window.draw(sprite2);
}
sprite3.setPosition(f.x * size, f.y * size);
window.draw(sprite3);
window.display();
}
return 0;
}
In your Tick() function you can check whether the head bumps into anything after everything has moved in the given direction. If it does, let main() know about it somehow: for example, return a bool which expresses if the game is over. Let's say this bool is called over.
So, add if (over) { window.close(); } inside your while (window.isOpen()) loop (right after calling Tick()) to let main() reach return 0; and finish the program.
EDIT: Think about using std::deque for moving your snake using less code and time: you'd be able to just pop_back() the snake tile farthest from the head and push_front() the new tile where the head currently is (after a tick), simulating crawling one step forwards.
Anyway, after having moved your snake you can check each of its body tiles whether it has the same coordinates as its head. If it does, it means your snake crashed into its tail so the game is over.
// in Tick():
// ...other logic...
tiles.pop_back();
tiles.push_front(new_head_position);
for (/* each tile of your snake except its head */) {
if (tile.x == head.x && tile.y == head.y) {
return false; // game over
}
}
return true; // everything is fine
Okay so I am a college student and our professor gave us this code to examine, and I was wondering if there was another way to do this but for OS X. My professor is using a HANDLE which I barely understand what that is, the professor was telling me he create the HANDLE as a pointer to the output stream so what would be the equivalent to it for mac since we don't have #include Windows.h obviously. Everything you see in this code is my professor's, including the comments.
//This is an example of a simple platformer made in the console. This
//makes no claims as the best way of doing things as I created this
//live before a class (while taking suggestions from them).
#include <iostream>
#include <string>
#include <vector>
#include <Windows.h>
using namespace std;
const int MAX_ROWS = 20;
const int MAX_COLS = 60;
//this is a reference to cout (we got this when we changed the output color)
//we can use this to setCursorPosition
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
//this is the place that we can set the cursor to when we are not using it
COORD zero;
//basic cardinal directions
enum Direction
{
UP = 8,
DOWN = 2,
RIGHT = 6,
LEFT = 4,
NORTH = UP,
SOUTH = DOWN,
EAST = RIGHT,
WEST = LEFT
};
//each place on the gameboard is a tile (tiles in this game are 1 character in length, though they do not have to be)
class Tile
{
public:
char display;
bool isPassible;
COORD pos;
Tile(char d, bool b, int y, int x)
{
display = d;
isPassible = b;
pos.X = x;
pos.Y = y;
}
void Display()
{
SetConsoleCursorPosition(output, pos);
cout << display;
SetConsoleCursorPosition(output, zero);
}
};
class Player
{
public:
COORD pos;
char display;
int JumpAmt;
//player constructor (x and y are starting location)
Player(int x, int y)
{
pos.X = x;
pos.Y = y;
display = 'C';
JumpAmt = 0;
}
//This gets the input and decides how to use it (this should be called in the main game loop)
bool Act(vector<vector<Tile>> GameBoard)
{
bool didMove = false;
COORD oldPos;
oldPos.X = pos.X;
oldPos.Y = pos.Y;
if (GetAsyncKeyState(VK_RIGHT) & 0x8000)
{
//make sure the movement is not off the game board and that there is not a wall in the way
if (pos.X + 1 < MAX_COLS && GameBoard[pos.Y][pos.X + 1].isPassible)
{
//actually move the character
pos.X += 1;
didMove = true;
}
}
if (GetAsyncKeyState(VK_LEFT) & 0x8000)
{
if (pos.X - 1 > 0 && GameBoard[pos.Y][pos.X - 1].isPassible)
{
pos.X -= 1;
didMove = true;
}
}
//You can only jump if you are on the ground
if (pos.Y + 1 < MAX_ROWS && !(GameBoard[pos.Y + 1][pos.X].isPassible))
{
if (GetAsyncKeyState(VK_UP) & 0x8000)
{
if (pos.Y - 1 > 0 && GameBoard[pos.Y - 1][pos.X].isPassible)
{
pos.Y -= 1;
didMove = true;
JumpAmt = 4;
}
}
}
//When you are not jumping fall (gravity)
if (JumpAmt == 0)
{
if (pos.Y + 1 < MAX_ROWS && GameBoard[pos.Y + 1][pos.X].isPassible)
{
pos.Y += 1;
didMove = true;
}
}
//This is what happens during your jump
if (JumpAmt > 0)
{
JumpAmt--;
if (pos.Y - 1 > 0 && GameBoard[pos.Y - 1][pos.X].isPassible)
{
pos.Y -= 1;
didMove = true;
}
}
//If you did move anywhere then update the board
if (didMove)
{
Display(oldPos, GameBoard);
}
return didMove;
}
void Display()
{
//draw myself at my position
SetConsoleCursorPosition(output, pos);
cout << display;
SetConsoleCursorPosition(output, zero);
}
void Display(COORD fix, vector<vector<Tile>> GameBoard)
{
//clear my old position
GameBoard[fix.Y][fix.X].Display();
Display();
}
};
int main()
{
//zero is used after anything is drawn to reset the cursor (this should never be changed after this)
zero.X = 0;
zero.Y = 0;
//this is a 2 dimentional array of tiles
vector<vector<Tile>> GameBoard;
//init all the tiles to blank (we will later add in platforms and stuff over top of these)
for (int row = 0; row < MAX_ROWS; row++)
{
vector<Tile> thisRow;
for (int col = 0; col < MAX_COLS; col++)
{
thisRow.push_back(Tile(' ', true, row, col));
}
GameBoard.push_back(thisRow);
}
//Build the game specific tiles (in a perfect world these would be read in from a file)
GameBoard[4][2] = Tile('-', false,4,2);
GameBoard[4][3] = Tile('-', false, 4,3);
GameBoard[4][4] = Tile('-', false, 4,4);
GameBoard[4][5] = Tile('-', false, 4,5);
GameBoard[4][6] = Tile('-', false, 4,6);
GameBoard[7][9] = Tile('-', false, 7,9);
GameBoard[7][10] = Tile('-', false, 7,10);
GameBoard[5][10] = Tile('-', false, 5,10);
GameBoard[8][14] = Tile('*', false, 8, 14); //this marks the win square
//display the board once
for (int row = 0; row < MAX_ROWS; row++)
{
for (int col = 0; col < MAX_COLS; col++)
{
GameBoard[row][col].Display();
}
}
//Bob is our hero
Player bob = Player(3, 3);
while (true)
{
bob.Act(GameBoard);
bob.Display();
Sleep(50);
//if bob falls down he dies
if (bob.pos.Y > 18)
{
bob.pos.X = 3;
bob.pos.Y = 3;
//bob.display = 65 + rand() % 26;
}
//if bob gets here he wins
if (bob.pos.Y == 7 && bob.pos.X == 14)
{
COORD pos;
pos.Y = 20;
pos.X = 0;
SetConsoleCursorPosition(output, pos);
cout << "You are Awesome";
break;
}
}
COORD pos;
pos.Y = 21;
pos.X = 0;
SetConsoleCursorPosition(output, pos);
system("Pause");
return 0;
}
Everytime I run the code it says
Vector subscript OUT of range.
I've looked at other SFML vector Questions on "stackoverflow" and none of them have answer of my questions or worked. What I'm trying to do is:
vector<sf::Sprite> snake_part;
sf::Sprite sprite;
for (int i = 0; i <= 10; --i) {
snake_part.push_back(sprite);
cout << "Vector size : " << snake_part.size() << endl;
snake_part[i].setTexture(Snake_Part_Texture);
if (i > 0) {
x1[i] -= 10;
}
}
This is the Part of the code that doesn't work.
OUTPUT:
Vector size : 1
Vector size : 2
It's supposed to count to "10", but stops at "2" for some reason and Comes with the "Vector subscript out of range" error as well.
Full Code:
#include <SFML/Graphics.hpp>
#include <iostream>
#include <vector>
using namespace std;
int main() {
//=========================================================
// Coordinates
float y = 330; float x = 150;
float x1[10]; x1[0] = x;
float y1[10]; y1[0] = y;
// Texture
sf::Texture floorText;
if (!floorText.loadFromFile("Floor_Snake_SFML.png")) {
cout << "Floor_Snake_SFML.COULD_NOT_LOAD: [Error]" << endl;
}
sf::Texture Snake_Part_Texture;
if (!Snake_Part_Texture.loadFromFile("Snake_Part_Sprite.png")) {
cout << "Snake_Part_Texture.COULD_NOT_LOAD: [Error]" << endl;
}
// Sprite_floor
sf::Sprite floor;
floor.setTexture(floorText);
floor.setPosition(0, 320);
// vector <sprite> -- (snake)
vector<sf::Sprite> snake_part;
sf::Sprite sprite;
for (int i = 0; i <= 10; --i) {
snake_part.push_back(sprite);
cout << "Vector size : " << snake_part.size() << endl;
snake_part[i].setTexture(Snake_Part_Texture);
if (i > 0) {
x1[i] -= 10;
}
}
//=========================================================
sf::RenderWindow window(sf::VideoMode(640, 480), "<snake>");
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
// Close Window
case sf::Event::Closed:
window.close();
break;
// Do [x] if KeyPressed-
case sf::Event::KeyPressed:
switch (event.key.code) {
// [A] -pressed-
case sf::Keyboard::A:
for (int j = 1; j <= 10; j++) {
x1[j] = x1[j - 1]; y1[j] = y1[j - 1];
}
x1[0] -= 10;
for (int k = 1; k <= 10; k++) {
snake_part[k].setPosition(x1[k], y1[k]);
}
break;
// [D] -pressed-
case sf::Keyboard::D:
break;
// [Space] -pressed-
case sf::Keyboard::Space:
break;
}
break;
}
}
window.clear(); // ===============================
window.draw(floor);
window.draw(snake_part[0]);
window.display(); // ===============================
}
return 0;
}
If you want a more detailed Error and synopsis of the Program, just comment, Also thanks in Advance, and if anyone know a better way instead of Vector to create 10 Sprites without having to do this 10 times:
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, 10, 10));
float x = 320, y = 240;
sprite.setPosition(x, y);
then I would be REALLY grateful.
-Thanks in advance.
The error more than likely comes from this line:
for (int i = 0; i <= 10; --i)
I don't know what you meant to do with that line, but more than likely it was supposed to be ++i instead of --i.