Graphics Error, Why is the program Crashing? - c++

I am trying to make a bar for each object of the class test. There's a private variable, status. If the value of status == 0 the bar changes color to red else it changes color to green. After multiple inputs from the for loop, the graphics window of the program crashes. Please assist me where am I doing wrong?
/* bar example */
#include <iostream>
#include <graphics.h>
using namespace std;
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
class test
{
private:
int x;
public:
test()
{
}
int getX()
{
if(x==0)
{
cout << "Room Empty";
}
else
if (x==1)
{
cout << "Room Occupied";
}
return x;
}
void setX(int check)
{
x=check;
this->update();
}
void update()
{
//Block to change the colour of the bar on the screen
if(x==0)
{
setfillstyle(INTERLEAVE_FILL,RED);
bar(100,100,20,20);
}
else
if(x==1)
{
setfillstyle(INTERLEAVE_FILL,BLUE);
bar(100,100,20,20);
}
}
};
int main(void)
{
/* request autodetection */
int gdriver = DETECT, gmode, errorcode;
int midx, midy, i;
/* initialize graphics and local variables */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) { /* an error occurred */
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(0); /* terminate with an error code */
}
int x;
test object;
for(int i=0;i<20;i++)
{
cout << "Enter 0 for red, 1 for Blue: ";
cin >> x;
object.setX(x);
}
//getch();
/* clean up */
closegraph();
return 0;
}

Related

How to properly use structs in c++?

I have a data structure in a header file of a player and a goblin that looks like this:
#ifndef GLOBALVAR_H
#define GLOBALVAR_H
#include <iostream>
#include <windows.h>
struct Player {
int x = 1, y = 1;
int health = 100;
int symbol = '#';
};
struct Goblin {
int x, y;
int health = 100;
int symbol = 'G';
};
#endif
I also have a data structure in a header file for the screen that looks like this:
#ifndef SCREEN_H
#define SCREEN_H
#include <iostream>
#include <windows.h>
struct Screen {
char screen[21][34] = {
"#################################",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#...............................#",
"#################################"
};
};
#endif
Finally, I have the main and generate c++ files that look like this respectively:
// main 'hub' for game
#include <iostream>
#include <windows.h>
#include "screen.h"
#include "generate.h"
#include "globalVar.h"
using namespace std;
bool running = true;
int main() {
struct Player p;
struct Screen s;
while(running) {
system("cls");
s.screen[p.y][p.x] = p.symbol;
draw();
p.health--;
system("pause>nul");
}
return 0;
}
// generates the map and draws the screen
#include <iostream>
#include <windows.h>
#include "screen.h"
#include "globalVar.h"
using namespace std;
int generate() {
return 0;
}
int draw() {
struct Screen s;
struct Player player;
for(int i = 0; i < 20; i++) {
cout << s.screen[i] << endl;
}
for(int i = 0; i < 1; i++) {
cout << "HP: " << player.health << endl;
}
return 0;
}
When I run main.cpp I want it to display a '#' symbol at 1, 1 of the array. When I run the code it instead displays a period in the place of it. What is happening here?
Image of what's being displayed:
https://imgur.com/a/RiWoDJ5
You have created two different Screens. The one in main() is completely different from the one in draw(), because they are in different scopes. You can pass a Screen as an argument to draw() to fix this.
You can also make draw() a function of Screen, as Nathan pointed out in the comments, and then call s.draw() in main().
Also, unlike in C, there is no need to put struct before every use of a struct. Simply put Screen s; instead of struct Screen s;
Example of draw() taking a parameter of type Screen:
int draw(Screen s) {
Player player;
for (int i = 0; i < 20; i++) {
cout << s.screen[i] << endl;
}
for (int i = 0; i < 1; i++) {
cout << "HP: " << player.health << endl;
}
return 0;
}
Example of draw() in Screen:
struct Screen {
static char screen[21][34];
int draw() {
Player player; //think about passing this as a parameter instead, not making one every time, because this one is inaccessible to everyone except this function
for (int i = 0; i < 20; i++) {
cout << screen[i] << endl;
}
for (int i = 0; i < 1; i++) {
cout << "HP: " << player.health << endl;
}
return 0;
}
};
Then, call it like:
s.draw();
I would go a different route and use inheritance and constructors:
struct Item
{
int m_x, m_y; // Every item has a position.
char m_symbol;
Item (char symbol, int x_pos = 1, int y_pos = 1)
: m_symbol(symbol), m_x(x_pos), m_y(y_pos)
{ ; }
};
struct Player : public Item // A player is an item
: Item('#', 1, 1)
{
};
struct Goblin : public Item // A goblin is an item
: Item ('G', 5, 4)
{
};
std::vector<std::vector<Item *>> game_board;
//...
Goblin * p_goblin = new Goblin;
game_board[p_goblin->y][p_goblin->x] = p_goblin;

Crash when using arrays of sf::Text

When I load and set font, app crashes and debugger shows me 0xc0000005 at line in MainMenu.cpp (exception is reported by sfml-graphics-d-2.dll):
window.draw(menu.at[i]);
This is line in for loop.
Btw. every time I close my app I have an error "Run-Time Check Failure #2 - Stack around the variable 'window' was corrupted." and debugger show end of main().
MainMenu.h:
#include <SFML/Graphics.hpp>
class MainMenu
{
public:
MainMenu();
void draw(sf::RenderWindow& window);
void MoveUp();
void MoveDown();
private:
std::array<sf::Text,3> menu;
sf::Font arial;
unsigned int cursor{ 0 };
};
MainMenu.cpp:
#include "MainMenu.h"
#include <SFML/Graphics.hpp>
#include <iostream>
constexpr int PLAY{ 1 };
constexpr int SETTINGS{ 2 };
constexpr int EXIT{ 3 };
MainMenu::MainMenu()
{
arial.loadFromFile("ArialUnicodeMS.ttf");
menu[0].setFont(arial);
menu[0].setCharacterSize(40);
menu[0].setFillColor(sf::Color::White);
menu[0].setString("Play!");
menu[0].setPosition(sf::Vector2f(400, PLAY * 40));
menu[1].setFont(arial);
menu[1].setCharacterSize(40);
menu[1].setFillColor(sf::Color::White);
menu[1].setString("Settings");
menu[1].setPosition(sf::Vector2f(400, SETTINGS * 40));
menu[2].setFont(arial);
menu[2].setCharacterSize(40);
menu[2].setFillColor(sf::Color::White);
menu[2].setString("Exit");
menu[2].setPosition(sf::Vector2f(400, EXIT * 40));
}
void MainMenu::draw(sf::RenderWindow& window)
{
for (int i = 0; i < 3; i++)
{
window.draw(menu[i]);
}
}
void MainMenu::MoveUp()
{
if (cursor - 1 >= 0)
{
std::cout << "moved up!";
menu[cursor].setFillColor(sf::Color::White);
cursor--;
menu[cursor].setFillColor(sf::Color::Red);
}
}
void MainMenu::MoveDown()
{
if (cursor + 1 < 3)
{
std::cout << "moved down!";
menu[cursor].setFillColor(sf::Color::White);
cursor++;
menu[cursor].setFillColor(sf::Color::Red);
}
}
main.cpp:
#include "Game.h"
#include "MainMenu.h"
#include "ConstState.h"
#include "Settings.h"
#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode(800,600), "test");
Game game;
MainMenu menu;
Settings settings;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::KeyReleased:
switch (event.key.code)
{
case sf::Keyboard::Up:
menu.moveUp();
break;
case sf::Keyboard::Down:
menu.moveDown();
break;
case sf::Keyboard::Return:
switch (menu.getCursor())
{
case 0:
std::cout << "play";
game.run(window);
break;
case 1:
std::cout << "settings";
break;
case 2:
window.close();
break;
}
break;
}
break;
case sf::Event::Closed:
window.close();
break;
}
}
window.clear(sf::Color::Red);
menu.draw(window);
window.display();
}
return 0;
}
In MainMenu::MoveUp() you write: if (cursor - 1 >= 0) ...
First of all, this condition is always true: cursor is an unsigned int, so it has no other options but to be >= 0.
Secondly, in the case when cursor is 0, your cursor - 1 yields the maximum value of unsigned int (as it wraps on overflow). As a result, menu[cursor].setFillColor... causes undefined behaviour because you give your std::array<sf::Text, 3> menu an invalid index.
Try fixing this and check if the error shows up again.

Game infrastructure NOT working properly (c++)

I have been designing my c++ console game and I have a question about the game loop. Whenever the game loops, I end up reinitializing my velocity variables in the constructor which sets them to "0". I have a couple ideas on how to solve this but it ends up ruining my game infrastructure and after a while gets confusing.
Can someone please tell me how to prevent my velocity variables from being reinitialized.
BTW I'll find out how to group my headers better later.
FPS.timerMilli(1) is a function that counts 1 millisecond before exiting function. (Trying to control FPS).
rectangle.cpp:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include "rectangle.h"
void rectangle::rectangleDrawPos(int h, int k) {
// Draw top of rectangle
for (int verticle = 1; verticle <= h; verticle += 1) {
std::cout << "\n";
}
for (int horizontal = 1; horizontal <= h; horizontal += 1) {
std::cout << " ";
}
for (int x = 1; x <= width; x += 1) {
std::cout << ".";
}
std::cout << "\n";
//Number of sides
midWidth = width - 2;
for (int y = 1; y <= height; y+=1) {
//Draw sides
for (int x = 1; x <= h; x += 1) {
std::cout << " ";
}
std::cout << ":";
for (int x = 1; x <= midWidth; x+=1) {
std::cout << " ";
}
std::cout << ":\n";
}
//Bottom of rectangle
for (int x = 1; x <= h; x += 1) {
std::cout << " ";
}
for (int x = 1; x <= width; x += 1) {
std::cout << ".";
}
std::cout << "\n";
}
//constructor
rectangle::rectangle(int locHeight, int locWidth) {
width = locWidth;
height = locHeight;
}
rectangle.h:
#ifndef RECTANGLE_H
#define RECTANGLE_H
class rectangle {
//Variables
int height, width, midWidth;
public:
//functions
void rectangleDrawPos(int h, int k);
//constructor
rectangle(int locHeight, int locWidth);
};
#endif
MyGame.cpp:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <ctime>
#include "timer.h"
#include "config.h"
#include "IOMovement.h"
#include "rectangle.h"
int main(){
//object def
timer FPS;
config startupConfig;
IOMovement IO;
//config
startupConfig.Set_Consol_Size(startupConfig.half_screen_Size, GetSystemMetrics(SM_CYSCREEN));
startupConfig.Position_Consol(-6, 0);
//Game Loop
while (1==1) {
FPS.timerMilli(1);
//Game Startup
IO.IOStartup();
//map
//ai
}
//exit
return 0;
}
IOMovement.cpp:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include "IOMovement.h"
#include "rectangle.h"
#define W_KEY 0x57
#define S_KEY 0x53
#define A_KEY 0x41
#define D_KEY 0x44
#define R_KEY 0x52
void IOMovement::IO() {
rectangle player(15, 5);
if (GetAsyncKeyState(W_KEY)) {
system("CLS");
velocityVerticle--;
player.rectangleDrawPos(velocityHorizontal, velocityVerticle);
}
if (GetAsyncKeyState(S_KEY)) {
system("CLS");
velocityVerticle++;
std::cout << "Working\n";
player.rectangleDrawPos(velocityHorizontal, velocityVerticle);
}
if (GetAsyncKeyState(A_KEY)) {
system("CLS");
velocityHorizontal--;
player.rectangleDrawPos(velocityHorizontal, velocityVerticle);
}
if (GetAsyncKeyState(D_KEY)) {
system("CLS");
velocityHorizontal++;
player.rectangleDrawPos(velocityHorizontal, velocityVerticle);
}
}
void IOMovement::IOStartup() {
//Variable decleration
velocityVerticle = 0;
velocityHorizontal = 0;
//Functions
IO();
}
IOMovement.h:
#ifndef IOMOVEMENT_H
#define IOMOVEMENT_H
class IOMovement {
int velocityVerticle, velocityHorizontal;
bool variableInitialization;
void IO();
public:
void IOStartup();
};
#endif
If you need your variable to retain it's value you could turn them into static variables.

Unhandled exception error Visual Studio 2012 and Allegro 4

I´m using allegro 4.4.2 on Visual Studio 2012 for a school project. Allegro is installed and working, and I'm trying to get it to load a map.txt file which is located in the project folder. When debugging, allegro freezes and becomes incredibly slow and throws an unhandled exception, violation access code at me.
This is Map.h:
#include <allegro.h>
#include "Global.h"
#include <fstream>
using namespace std;
class Map
{
public:
Map();
~Map();
void Init();
void Update();
void Draw(BITMAP *Buffer);
void LoadMap (const char*filename);
private:
int loadCounterX;
int loadCounterY;
int mapSizeX;
int mapSizeY;
int MapFile[20][15];
};
And this is Map.cpp:
#include "Map.h"
Map::Map()
{
}
Map::~Map()
{
}
void Map::Init()
{
loadCounterX = loadCounterY = 0;
Map::LoadMap("map1.txt");
}
void Map::Update()
{
}
void Map::Draw(BITMAP *Buffer)
{
for (int i = 0; 1 < mapSizeX; i++)
{
for (int j = 0; j < mapSizeY; j++)
{
if (MapFile[i][j] == 1)
{
rectfill(Buffer, i*BlockSize, j*BlockSize, i*BlockSize + BlockSize, j*BlockSize + BlockSize, makecol(0, 255, 255));
}
else if (MapFile[i][j] == 2)
{
rectfill(Buffer, i*BlockSize, j*BlockSize, i*BlockSize + BlockSize, j*BlockSize + BlockSize, makecol(0, 255, 0));
}
}
}
}
void Map::LoadMap(const char*filename)
{
ifstream openfile (filename);
if (openfile.is_open())
{
openfile >> mapSizeX >> mapSizeY;
while (!openfile.eof())
{
openfile >> MapFile[loadCounterX][loadCounterY];
loadCounterX ++;
if (loadCounterX >= mapSizeX)
{
loadCounterX = 0;
loadCounterY ++;
}
}
loadCounterX = loadCounterY = 0;
} //File is opened
else
{
allegro_message ("Map File couldn't be found");
}
}
and here is my main file:
#include <allegro.h>
#include "Player.h"
#include "Global.h"
#include "Camera.h"
#include "Map.h"
using namespace std;
volatile int counter = 0;
void Increment ()
{
counter ++;
}
int main (void)
{
allegro_init();
install_keyboard();
install_mouse();
install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, "A");
set_color_depth(32);
set_gfx_mode (GFX_AUTODETECT_WINDOWED, ScreenWidth, ScreenHeight, 0, 0);
LOCK_VARIABLE (counter);
LOCK_FUNCTION (Increment);
install_int_ex (Increment, BPS_TO_TIMER(100));
BITMAP *Buffer = create_bitmap (6000, ScreenHeight);
bool done = false;
Player player;
Camera camera;
Map map;
player.Init();
camera.Init();
map.Init();
while (!done)
{
while (counter > 0)
{
//Input
if (key[KEY_ESC])
done = true;
//Update
map.Update();
player.Update();
camera.Update(player.x, player.y);
counter --;
}
//Draw
map.Draw(Buffer);
player.Draw(Buffer);
camera.Draw(Buffer);
clear_bitmap(Buffer);
}
return 0;
}
END_OF_MAIN();
It crashes at this line
if (MapFile[i][j] == 1)
everytime. All of the variables shown in "Autos" in Visual Studio turn red; "MapFile" "MapFile[i]" (which I don't understand.. shouldn't this just be "i"?) "j" "mapSizeY" and "this" However when I expand the "MapFile", the first 20 blocks are filled out correctly as they are in my map.txt file.
I'm completely lost and have no idea what to do... any help is greatly appreciated!
In void Map::Draw(BITMAP *Buffer) you use 1 < mapSizeX instead of i < mapSizeX.
You might also want to prevent calling Map::Draw when the Map::LoadMap wasn't called before.

Trouble changing class variable

I'm trying to write a small game where boxes drop down from the top of the window. But for some reason, I can't change a internal variable in the class, the y-coordinate. I don' knowif I'm missing something basic, but I can't find the bug.
Box.h
#pragma once
#include "SDL.h"
class Box
{
public:
Box();
~Box();
void setX (int a);
void setY (int a);
void setSpeed (int a);
void setSurface ();
void render(SDL_Surface *source, SDL_Window *win);
void update();
private:
int x;
int y;
int speed;
SDL_Surface *sur;
SDL_Rect rect;
};
Box.cpp
#include "Box.h"
#include "SDL_image.h"
#include <iostream>
void Box::setX(int a)
{
x = a;
}
void Box::setY (int a)
{
y = a;
}
void Box::setSpeed (int a)
{
speed = a;
}
void Box::setSurface()
{
sur = IMG_Load("C:/hello.bmp");
if (sur == NULL)
{
std::cout << IMG_GetError();
}
}
Box::Box()
{
speed = 5;
y = 0;
x = 3;
rect.x = 0;
rect.y = 0;
}
Box::~Box()
{
}
void Box::render(SDL_Surface *source, SDL_Window *win)
{
SDL_BlitSurface(sur, NULL, source, &rect);
SDL_UpdateWindowSurface(win);
}
void Box::update()
{
setY(y + speed); //I've also tried y = y + speed
rect.y = y;
}
main.cpp
#include "SDL.h"
#include "Box.h"
#include "SDL_image.h"
#include <iostream>
bool init();
void update(Box test);
void render(Box test);
SDL_Window *win;
SDL_Surface *source;
int main(int argc, char *argv[])
{
init();
bool quit = false;
SDL_Event e;
Box test;
test.setSurface();
test.render(source, win);
while (quit ==false)
{
while( SDL_PollEvent( &e ) != 0 )
{
if( e.type == SDL_QUIT )
{
quit = true;
}
}
update(test);
render(test);
}
return 0;
}
void update(Box test)
{
test.update();
}
void render(Box test)
{
test.render(source, win);
}
bool init()
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
{
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == NULL)
{
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
return 1;
}
source = SDL_GetWindowSurface(win);
return true;
}
update takes its Box argument by value, so a copy of the original Box is always made when update(test) is called. This copy is then modified, and the original is left unchanged. To fix this, make update take its argument by reference.
void update(Box& test);
void update(Box& test)
{
test.update();
}