Trying to use Vectors with SFML - c++

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.

Related

Vector Subscript Out of Range C++ SFML

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

Random shape and movement generation not drawing shape

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.

C++ - Blocks don't move and my array does not work

I'm trying to make a game using C++ in SFML for the first time.
Want : 6 blocks fall from random top to bottom.
Result : 1 block stay at the top.
How should I fix in this code?
#include <SFML/Graphics.hpp>
#include <vector>
#include <time.h>
using namespace sf;
using namespace std;
struct Position{
int x;
int y;
};
int main()
{
srand(time(NULL));
RenderWindow window(VideoMode(600, 480), "AVOID BLOCKS");
window.setFramerateLimit(60);
Texture t1, t2;
t1.loadFromFile("images/block.png");
t2.loadFromFile("images/cha2.png");
Sprite block(t1), cha2(t2);
Position blockPos;
blockPos.y = 0 + t1.getSize().y;
cha2.setPosition(300, 400);
float blockSpeed = 4;
const int size = 6;
vector<Sprite> blocks(6);
int n = 0;
auto bsize = t1.getSize();
for (int i = 0; i < 6; i++) {
blocks[n].setTexture(t1);
blocks[n].setPosition(rand()%10*bsize.x, 0);
n++;
}
while (window.isOpen())
{
Event e;
while (window.pollEvent(e)) {
if (e.type == Event::Closed)
window.close();
}
auto cha2_pos = cha2.getPosition();
if (Keyboard::isKeyPressed(Keyboard::Left)) {
if (cha2.getPosition().x < 0)
continue;
cha2.move(-5.0, 0.0);
}
if (Keyboard::isKeyPressed(Keyboard::Right)) {
if (cha2.getPosition().x > 600)
continue;
cha2.move(5.0, 0.0);
}
if (blockPos.y >= 480) {
blockPos.y = 0 + t1.getSize().y;
blockSpeed = blockSpeed + 0.2;
}
else
blockPos.y += blockSpeed;
for (int i = 0; i < blocks.size(); i++) {
if (FloatRect(cha2_pos.x + 3, cha2_pos.y + 3, 10, 10).
intersects(blocks[i].getGlobalBounds())) {
window.close();
}
}
window.clear();
window.draw(block);
window.draw(cha2);
window.display();
}
return 0;
}
The character at the bottom moves well.
I have no idea why block doesn't move and there's only one.
I think there's something wrong in the part starts "const int size".
Your program have two main problems. First of all, you don't draw all the blocks in the vector but you draw only the particular block you have made. This is why you see only one block on screen and not all the blocks you have create. The solution for this is:
for(auto& blk : blocks)
window.draw(blk);
The second problem affects the movement of the blocks. You have create a struct Position but you never associated with the blocks. So after you increase blockPos.y, you must move the blocks at that new blockPos.y. Explicit:
for(auto& blk : blocks)
blk.setPosition(blockPos.x, blockPos.y);
In this way you will have the problem that every block will be in the exact same position with the others because the blockPos variable is common for all blocks. A good idea is to make a class Block so which block to have his own position and movement. An example to what I say is:
class Block {
private:
Sprite block;
Position blockPos;
public:
Block(Texture& texture, int x, int y)
{
block.setTexture(texture);
blockPos.y = y;
blockPos.x = x; // save this value because you will need it
// every time you move the block
}
void setBlockPosition(float y)
{
blockPos.y = y;
}
Vector2<float> getBlockPosition()
{
return Vector2f(blockPos.x, blockPos.y);
}
void blockMovement(int y)
{
blockPos.y += y;
block.setPosition(blockPos.x, blockPos.y);
}
Sprite getSprite()
{
return block;
}
void Draw(RenderWindow& window)
{
window.draw(block);
}
};
After that I declare a vector with the new dynamic objects:
vector<Block*> blocks(6);
for(unsigned int i = 0; i < blocks.size(); i++)
{
blocks[i] = new Block(t1, rand()%10*t1.getSize().x ,0 - t1.getSize().y);
}
I change your if statements also:
for(unsigned int i = 0; i < blocks.size(); i++) //check for which block in the vector
{
if (blocks[i]->getBlockPosition().y >= 480) {
blocks[i]->setBlockPosition(0 - 200);
blockSpeed = blockSpeed + 0.2;
}
else {
blocks[i]->blockMovement(blockSpeed);
}
}
for (unsigned int i = 0; i < blocks.size(); i++) {
if (FloatRect(cha2_pos.x + 3, cha2_pos.y + 3, 10, 10)
.intersects(blocks[i]->getSprite().getGlobalBounds())) {
window.close();
}
}
Don't forget at the end to delete the objects because they was allocate dynamically:
for(unsigned int i = 0; i < blocks.size(); i++)
delete blocks[i];
return 0;

Why doesn't the Player.x and Player.y variables change?

Edit #2: Ok, I did another *.cpp to check if the codes for Arrow Keys were right. Doing that, I noticed keyPressed variable in detectKeyPressing() had the wrong type of variable, so I changed it from char to int and changed the codes.
Once I did that, it worked. Now I have put the limits, so the Player cannot go outside the square. But I have another problem, the movement is too tough and if you press the keys too fast, the instructions run with a annoying delay. I know I should use either Sleep(ms) or Delay(ms), but I don't know when I should use it.
This is the new code:
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <Windows.h>
using namespace std;
int detectKeyPressing() {
// 0: Escape
// 1: Enter
//2: Up
// 3: Left
// 4: Down
// 5: Right
int keyPressed = 0;
while (keyPressed != 27) {
if (keyPressed == 0 || keyPressed == 224) {
keyPressed = _getch(); //First value of _getch() when any of the arrow keys are pressed is "224", the next one is the code depending of which arrow you pressed
}
else if (keyPressed == 13) {
return 1;
}
else {
switch (keyPressed) {
//Up
case 72:
return 2;
break;
//Left
case 75:
return 3;
break;
//Down
case 80:
return 4;
break;
//Right
case 77:
return 5;
break;
//Default
default:
return -1;
break;
}
}
};
return 0;
};
int mainMenu() {
int enterPressed = 0;
cout << "Press Enter to Begin, or ESC to exit" << endl;
enterPressed = detectKeyPressing();
system("cls");
return enterPressed;
};
void draw(int playerX, int playerY) {
//Player coordinates, made for testing
cout << "Player.x = " << playerX << endl << "Player.y = " << playerY << endl;
//The next 8 spaces go blank
for (int i = 1; i < 8; i++) {
cout << endl;
}
//Square Limit Making
//Top Limit
for (int iw = 1; iw < 80; iw++) {
cout << "-";
}
cout << endl;
//Border limits and inside the Square
for (int ih = 1; ih < 30; ih++) {
//Left border
cout << "|";
//Inside the Square
for (int iw = 1; iw < 78; iw++) {
if (iw == playerX && ih == playerY) {
cout << "a"; //This is supposed to be ♥ but I don't know how to put it in the screen with a cout
}
else {
cout << " ";
}
}
//Right border
cout << "|" << endl;
}
//Bottom limit
for (int iw = 1; iw < 80; iw++) {
cout << "-";
}
}
int main() {
//Hide cursor
HANDLE hCon;
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
cci.dwSize = 1;
cci.bVisible = FALSE;
SetConsoleCursorInfo(hCon, &cci);
//Variable Making
int gameStarted = -1; // 1 if game is running, 0 if not
//int t = 0; //Turn Counter, not useful for now
Sleep(200); //Wait to get a new seed
srand(time(NULL)); //Seed for rand()
//Menu Loop, remember, 1 if game starts running, 0 if you exit
while (gameStarted > 1 || gameStarted < 0) {
gameStarted = mainMenu();
}
//Like Void Start() in Unity
if (gameStarted == 1) {
int pressedKey = -1; //Creating pressedKey at Start
class Player {
public:
int life = 20;
int accuracy = 80 + (rand() % 100) / 20;
int damage = 5 + (accuracy / 10) + (rand() % 100) / 50;
bool isAlive = true;
int x = 39;
int y = 24;
int speed = 1;
};
class Enemy {
public:
int life = 100;
int satisfaction = 0;
bool isAlive = true;
bool isSatisfied = false;
int damage = 2 + (rand() % 100) / 20;
};
Player Player;
Enemy Enemy;
draw(Player.x, Player.y);
//Like Void Update() in Unity
while (gameStarted != 0) {
pressedKey = detectKeyPressing(); // Save detectKeyPressing()'s return in pressedKey
//Draw if proyectile is moving - not yet
//Draw if player is moving (pay attention specially to this part)
if (pressedKey == 0) {
gameStarted = 0; //if ESC is pressed, exit the loop and exits
}
//If any of the Arrow Keys are pressed
else if (pressedKey > 1 && pressedKey < 6) {
switch (pressedKey) {
//Up
case 2:
Sleep(200);
if (Player.y == Player.speed) {
Player.y = Player.speed; //Top Limit
}
else {
Player.y -= Player.speed;
}
break;
//Left
case 3:
Sleep(200);
if (Player.x == Player.speed) {
Player.x = Player.speed; //Left Limit
}
else {
Player.x -= Player.speed;
}
break;
//Down
case 4:
Sleep(200);
if (Player.y == 30 - Player.speed) {
Player.y = 30 - Player.speed; //Bottom Limit
}
else {
Player.y += Player.speed;
}
break;
//Right
case 5:
Sleep(200);
if (Player.x == 78 - Player.speed) {
Player.x = 78 - Player.speed; //Right Limit
}
else {
Player.x += Player.speed;
}
break;
};
system("cls"); //Erase all
draw(Player.x, Player.y); //Redraw everything, with Player.x or Player.y modified
};
};
};
return 0;
};
Edit #1: I fixed the mistakes you told me, here's the main function modified. It isn't working though.
int main(){
//Hide cursor
HANDLE hCon;
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
cci.dwSize = 50;
cci.bVisible = FALSE; //Changed "TRUE" to "FALSE"
SetConsoleCursorInfo(hCon, &cci);
//Variable Making
int gameStarted = -1; // 1 if game is running, 0 if not
//int t = 0; //Turn Counter, not useful for now
Sleep(200); //Wait to get a new seed
srand(time(NULL)); //Seed for rand()
//Menu Loop, remember, 1 if game starts running, 0 if you exit
while (gameStarted > 1 || gameStarted < 0) {
gameStarted = mainMenu();
}
//Like Void Start() in Unity
if (gameStarted == 1) {
int pressedKey = -1; //Creating pressedKey at Start
class Player {
public:
int life = 20;
int accuracy = 80 + (rand() % 100) / 20;
int damage = 5 + (accuracy / 10) + (rand() % 100) / 50;
bool isAlive = true;
int x = 39;
int y = 24;
int speed = 2;
};
class Enemy {
public:
int life = 100;
int satisfaction = 0;
bool isAlive = true;
bool isSatisfied = false;
int damage = 2 + (rand() % 100) / 20;
};
Player Player;
Enemy Enemy;
draw(Player.x, Player.y);
//Like Void Update() in Unity
while (gameStarted != 0) {
pressedKey = detectKeyPressing(); //Save detectKeyPressing()'s return in pressedKey
//Draw if proyectile is moving - not yet
//Draw if player is moving (pay attention specially to this part)
if (pressedKey == 0) {
gameStarted = 0; //if ESC is pressed, exit the loop and exits
}
//If any of the Arrow Keys are pressed
else if (pressedKey > 1 && pressedKey < 6) {
cout << "There's no problem in Else If statement"; //Couts made for testing
switch (pressedKey) {
cout << "There's no problem in Switch statement";
//Up
case 2:
Player.y -= Player.speed;
cout << "You moved Up";
break;
//Left
case 3:
Player.x -= Player.speed; //Fixed Left movement
cout << "You moved Left";
break;
//Down
case 4:
Player.y += Player.speed;
cout << "You moved Down";
break;
//Right
case 5:
Player.x += Player.speed;
cout << "You moved Right";
break;
};
//system("cls"); //Erase all
//draw(Player.x, Player.y); //Redraw everything, with Player.x and Player.y supposedly modified
};
};
};
return 0;
};
Initial Post: I'm trying to do something like an Undertale normal fight and now I'm doing the "dodging attacks" part, but I'm stuck at making the player move (Yep, that "a") because it didn't update when I press an arrow key (for movement). It is supposed to draw, and put the Player in Player.x and Player.y, so I did something in main() to edit these variables depending on the arrow key you pressed, and then erase and re-draw with the Player.x or Player.y modified.
Here's the code:
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <Windows.h>
using namespace std;
int detectKeyPressing(){
// 0: Escape
// 1: Enter
// 2: Up
// 3: Left
// 4: Down
// 5: Right
char keyPressed = 0;
while (keyPressed != 27){
if(keyPressed == 0){
keyPressed = _getch();
}
else if(keyPressed == 13){
return 1;
}
else{
switch (keyPressed) {
//Up
case 65:
return 2;
break;
//Left
case 68:
return 3;
break;
//Down
case 66:
return 4;
break;
//Right
case 67:
return 5;
break;
//Default
default:
return -1;
break;
}
}
};
return 0;
};
int mainMenu(){
int enterPressed = 0;
cout << "Press Enter to Begin, or ESC to exit" << endl;
enterPressed = detectKeyPressing();
system("cls");
return enterPressed;
};
void draw(int playerX, int playerY) {
//Player coordinates, made for testing
cout << "Player.x = " << playerX << endl << "Player.y = " << playerY << endl;
//The next 8 spaces go blank
for (int i = 1; i < 8; i++) {
cout << endl;
}
//Square Limit Making
//Top Limit
for (int iw = 1; iw < 80; iw++) {
cout << "-";
}
cout << endl;
//Border limits and inside the Square
for (int ih = 1; ih < 30; ih++) {
//Left border
cout << "|";
//Inside the Square
for (int iw = 1; iw < 78; iw++) {
if (iw == playerX && ih == playerY){
cout << "a"; //This is supposed to be ♥ but I don't know how to put it in the screen with a cout
}
else {
cout << " ";
}
}
//Right border
cout << "|" << endl;
}
//Bottom limit
for (int iw = 1; iw < 80; iw++) {
cout << "-";
}
}
int main(){
//Hide cursor
HANDLE hCon;
hCon = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
cci.dwSize = 50;
cci.bVisible = TRUE;
SetConsoleCursorInfo(hCon, &cci);
//Variable Making
int gameStarted = -1; // 1 if game is running, 0 if not
//int t = 0; //Turn Counter, not useful for now
Sleep(200); //Wait to get a new seed
srand(time(NULL)); //Seed for rand()
//Menu Loop, remember, 1 if game starts running, 0 if you exit
while (gameStarted > 1 || gameStarted < 0) {
gameStarted = mainMenu();
}
//Like Void Start() in Unity
if (gameStarted == 1) {
class Player {
public:
int life = 20;
int accuracy = 80 + (rand() % 100) / 20;
int damage = 5 + (accuracy / 10) + (rand() % 100) / 50;
bool isAlive = true;
int x = 39;
int y = 24;
int speed = 2;
};
class Enemy {
public:
int life = 100;
int satisfaction = 0;
bool isAlive = true;
bool isSatisfied = false;
int damage = 2 + (rand() % 100) / 20;
};
Player Player;
Enemy Enemy;
draw(Player.x, Player.y);
//Like Void Update() in Unity
while (gameStarted != 0) {
//Draw if proyectile is moving - not yet
//Draw if player is moving (pay attention specially to this part)
if (detectKeyPressing() == 0) {
gameStarted = 0; //if ESC is pressed, exit the loop and exits
}
//If any of the Arrow Keys are pressed
else if (detectKeyPressing() > 1 && detectKeyPressing() < 6) {
switch (detectKeyPressing()) {
//Up
case 2:
Player.y -= Player.speed;
break;
//Left
case 3:
Player.x += Player.speed;
break;
//Down
case 4:
Player.y += Player.speed;
break;
//Right
case 5:
Player.x += Player.speed;
break;
};
system("cls"); //Erase all
draw(Player.x, Player.y); //Redraw everything, with Player.x and Player.y supposedly modified
};
};
};
return 0;
};
I did a few tests and it seems that the else if in "//If any of the Arrow Keys is Pressed" part isn't running but I don't know why.
I would really appreciate any help you can provide. Sorry if anything isn't well written, I'm not a native english speaker.
Where you have this comment
//Draw if proyectile is moving - not yet add a variable to save your pressed key, something like
int pressedKey = detectKeyPressing();
Then, use that variable to check which condition is met within your if-else.
What’s happening is that you’re calling your function, thus asking/waiting for an input each time a condition is being checked.

Printing 2D array in full ignores edited values, prints initialised values

beginner to C++ and attempting a dungeon crawler beginner task, upon testing one of the classes I found that printing the 2D array works, however if it is edited and printed, it resets and prints original values it was initialised with.
InitGrid is used to initialize the array.
class MAP
{
public:
/*
Difficulty used in number of enemies and traps created.
1-5 Difficulty
| 1 - Too easy | 2 - Easy | 3 - Normal | 4 - Hard | 5 - Insane |
*/
int Difficulty = Hard; //### Temporary, user selection needs implemented ###
int SpawnPos;
int TPosX; //Treasure Postion, used to checkwinstate.
int TPosY; //Treasure Postion, used to checkwinstate.
char Grid[MAPHeight][MAPWidth];
void InitGrid()
{
for (int y = 0; y < 9; y++) //Row loop
{
for (int x = 0; x < 14; x++) //Column loop
{
Grid[y][x] = { '.' };
}
}
}
void PrintMap()
{
for (int y = 0; y < 9; y++) //This loops on the rows.
{
for (int PrintX = 0; PrintX < 14; PrintX++) //This loops on the columns
{
cout << Grid[y][PrintX] << " ";
}
cout << endl;
}
}
void GenerateEnemies()
{
for (int i = 0; i < Difficulty; i++)
{
int TotEnemies = (Difficulty * 1.5);
for (TotEnemies; TotEnemies == 0; TotEnemies--)
{
int x = rand() % (MAPWidth - 1);
int y = rand() % (MAPHeight - 1);
if (Grid[y][x] == '.')
{
Grid[y][x] = '#';
}
else
{
GenerateEnemies();
}
}
}
}
// Generate Enemies
void GenerateTraps()
{
for (int i = 0; i < Difficulty; i++)
{
int TotTraps = (Difficulty * 1.5);
for (TotTraps; TotTraps == 0; TotTraps--)
{
int x = rand() % (MAPWidth - 1);
int y = rand() % (MAPHeight - 1);
if (Grid[y][x] == '.')
{
Grid[y][x] = 'T';
}
else
{
GenerateTraps();
}
}
}
}
void GenerateTreasure()
{
int x = rand() % MAPWidth;
int y = rand() % MAPHeight;
/*
Randomly selects spawn location
uses tmp variables to overwrite
that grid location.
*/
if (Grid[y][x] == '.')
{
Grid[y][x] = 'X';
}
else
{
GenerateTreasure();
}
TPosX = x;
TPosY = y;
}
};
//PLAYER CLASS
class PLAYER : public MAP
{
public:
int Health = (Difficulty * 1.5);
int PPosX;
int PPosY;
char Direction; //Use cin to get user input after map is updated, used in switch case to move player.
void GenerateSpawn()
{
int x = rand() % (MAPWidth - 1);
int y = rand() % (MAPHeight - 1);
/*
Randomly selects spawn location
uses tmp variables to overwrite
that grid location.
*/
Grid[y][x] = 'P';
PPosX = x;
PPosY = y;
}
void AllowMove(int y, int x)
{
if (Grid[y][x] == '.')
{
Grid[y][x] = '#';
}
else if (Grid[y][x] == 'X')
{
//GameWin();
}
else if (Grid[y][x] == '#')
{
//DamagePlayer();
}
else {}
}
void MovePlayer()
{
switch (Direction)
{
case 'w':
{
int x = PPosX;
int y = (PPosY + 1);
void AllowMove(int y, int x);
}
break;
case 'a':
{
int x = (PPosX - 1);
int y = PPosY;
void AllowMove(int y, int x);
}
break;
case 's':
{
int x = (PPosX);
int y = PPosY;
void AllowMove(int y, int x);
}
break;
case 'd':
{
int x = (PPosX + 1);
int y = PPosY;
void AllowMove(int y, int x);
}
break;
default:
cout << "invalid character, try again." << endl;
Sleep(5000);
//Call function to retry
}
}
};
//######### End #########
//Main Function
int main() {
srand(time(NULL)); //Used to seed rand() values.
SetConsoleTitle(TEXT("Dungeon Crawler"));
//Objects
MAP Map;
PLAYER Player;
Map.InitGrid();
Player.GenerateSpawn();
//Map.GenerateTreasure();
//Map.GenerateEnemies();
//Map.GenerateTraps();
Map.PrintMap();
cout << endl;
}
However, when I run these, I get the following image:
I've attempted debugging in visual studio using breakpoints and at some point it does set the grid value to 'P' but I couldn't find where I gets 'reset' for lack of a better term.
char Grid[MAPHeight][MAPWidth]; needs to be moved outside of the class as a global variable. Currently as the PLAYER class inherits from the MAPS class, when GenerateSpawn() edits the Grid that is created specific to the object linked to PLAYER.
When it is a global variable, it is separate, then when edited by GenerateSpawn() and called by void PrintMap() they both use the same Grid.
That way when it is printed to console it correctly prints out the map.
Answered my own question in case someone else stumbles upon this.