I'm trying to write a game of checkers in SDL. When I compile my code, I get this error:
std::basic_ifstream>::basic_ifstream(conststd::basic_ifstream> &)' : attempting to reference a deleted function
From what I can find on the web, this means that the compile has helpfully deleted my constructor for some reason, and now it can't find it again. (Bad organization if you ask me) Why could this be?
Board.h:
#include <fstream>
class Board
{
public:
SDL_Surface * boardSurface;
int boardArray[8][8];
private:
std::ifstream boardFile;
SDL_Surface * blackPiece;
SDL_Surface * whitePiece;
SDL_Surface * darkSquare;
SDL_Surface * lightSquare;
public:
Board(char filename[], SDL_PixelFormat * format);
private:
void loadFile(char filename[]);
void makeSurface();
void debugPrint();
void debugBlit();
};
Board.cpp:
#include <SDL.h>
#include <fstream>
#include <iostream>
#include <stdlib.h>
#include "board.h"
#include "loaders.h"
Board::Board(char filename[], SDL_PixelFormat * format)
{
//inits images
loaders imageLoader;
blackPiece = imageLoader.load_image("images/blackPiece.png", format);
whitePiece = imageLoader.load_image("images/whitePiece.png", format);
darkSquare = imageLoader.load_image("images/darkSquare.png", format);
lightSquare = imageLoader.load_image("images/lightSquare.png", format);
boardSurface = SDL_CreateRGBSurface(0, 780, 480, 8, 0, 0, 0, 0);
loadFile(filename);
debugPrint();
debugBlit();
}
void Board::loadFile(char filename[])
{
boardFile.open(filename);
char currentLine[9] = {};
for (int line = 0; line <= 7; line++)
{
boardFile.getline(currentLine, 9);
for (int square = 0; square <= 7; square++)
{
int currentSquare = (int)currentLine[square] - '0';
boardArray[line][square] = currentSquare;
}
}
}
void Board::makeSurface()
{
}
void Board::debugPrint()
{
for (int line = 0; line <= 7; line++)
{
for (int square = 0; square <= 7; square++)
{
std::cout << boardArray[line][square];
}
std::cout << std::endl;
}
}
void Board::debugBlit()
{
for (int y = 0; y <= 4; y++)
{
if (SDL_BlitSurface(blackPiece, NULL, boardSurface, NULL) != 0)
{
std::cout << SDL_GetError();
}
}
}
The error happens because you have an std::ifstream data member, and you are probably trying to copy a Board somewhere, or have some code that requires the copy constructor to be accessible.
std::ifstream boardFile;
The Board compiler-provided copy constructor tries to copy the stream, but the stream is not copyable. So you have to either provide your own copy constructor to do something clever, or remove code that requires the Board copy constructor.
Related
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;
I'm using SDL library for my homework at university, the program run smoothly at first but then I created a class using SDL as member like this:
#pragma once
#include <SDL.h>
#include <string>
#include <SDL_image.h>
#include <cstring>
using namespace std;
class Anh
{
public:
SDL_Surface * SURFACE;
SDL_Texture * TEXTURE;
SDL_Rect RECT;
void ganAnh(string a, SDL_Renderer *renderer);
void setRect(int a, int b, int c, int d);
};
and Object.cpp
#include "Object.h"
void Anh::ganAnh(string a, SDL_Renderer * renderer)
{
SURFACE = IMG_Load(a.c_str);
TEXTURE = SDL_CreateTextureFromSurface(renderer, SURFACE);
}
void Anh::setRect(int a, int b, int c, int d)
{
RECT.x = a;
RECT.y = b;
RECT.w = c;
RECT.h = d;
}
This is the declaration of variable in Source.cpp before main:
Anh Image;
Anh Bar;
But when I used this class members in my function
void LoadBar(SDL_Renderer *renderer, string a)
{
SDL_RenderCopy(renderer, Image.TEXTURE, NULL, &Image.RECT);
Bar.RECT.x = (720 - Bar.RECT.w * a.length()) / 2;
for (int i = 0; i < a.length(); i++)
{
SDL_RenderCopy(renderer, Bar.TEXTURE, NULL, &Bar.RECT);
Bar.RECT.x += 50;
if (i == a.length() - 1) Bar.RECT.x = (720 - Bar.RECT.w * a.length()) / 2;
}
}
It reported C2228 left of '.TEXTURE' must have class/struct/union and
C2660 'SDL_RenderCopy': function does not take 2 arguments
Every time I access class member I got that error. Please help me!
I don't see an instantiation for Bar in your function LoadBar.
For Example:
Anh * Bar = new Anh();
Edit:
Ok, the declaration seems to be not the problem.
But, did you have looked here?
https://msdn.microsoft.com/en-gb/library/3y365xw6.aspx
-> So, if you have not declared another Image or Bar variable the access to your member is not correct.
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.
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();
}
Hi I made a level generator with a 3D Buzz tutorial called Evil Monkeys.
I generated a level but I can't get it to draw on the screen.
My code:
Level.cpp
#include "Level.h"
#include <stdlib.h>
#include "Sprite.h"
Level::Level(drawEngine *de, int w, int h)
{
drawArea = de;
width = w;
height = h;
gamer = 0;
//create memory for our level
level = new char *[width];
for(int x = 0; x < width; x++)
{
level[x] = new char[height];
}
//create the level
createLevel();
drawArea->setMap(level);
}
Level::~Level()
{
for(x = 0; x < width; x++)
delete []level[x];
delete [] level;
}
void Level::createLevel(void)
{
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
int random = rand() % 100;
if (y == 0 || y == height - 1 || x == 0 || x == width - 1)
{
level[x][y] = TILE_WALL;
}
else
{
if (random < 90 || (x < 3 && y < 3))
level[x][y] = TILE_EMPTY;
else
level[x][y] = TILE_WALL;
}
}
}
}
void Level::draw(void)
{
// level to be drawn here
drawArea->drawBackground();
}
Level.h
#ifndef LEVEL_H
#define LEVEL_H
enum
{
TILE_EMPTY,
TILE_WALL
};
#include "drawEngine.h"
class Character;
class Level
{
public:
Level(drawEngine *de, int width = 30, int height = 20);
~Level();
int x;
int y;
void addPlayer(Character *p);
void update(void);
void draw(void);
bool keyPress(char c);
protected:
void createLevel(void);
private:
int width;
int height;
char **level;
Character *gamer;
drawEngine *drawArea;
};
#endif
Game.cpp
#include "Game.h"
#include <conio.h>
#include <iostream>
#include "drawEngine.h"
#include "Character.h"
#include <windows.h>
using namespace std;
//this will give ME 32 fps
#define GAME_SPEED 25.33
bool Runner::run()
{
level = new Level(&drawArea, 30, 20);
drawArea.createBackgroundTile(TILE_EMPTY, ' ');
drawArea.createBackgroundTile(TILE_WALL, '+');
drawArea.createSprite(0, '$');
gamer = new Character(&drawArea, 0);
level->draw();
char key = ' ';
startTime = timeGetTime();
frameCount = 0;
lastTime = 0;
posX = 0;
while (key != 'q')
{
while(!getInput(&key))
{
timerUpdate();
}
//gamer->keyPress(key);
//cout << "Here's what you pressed: " << key << endl;
}
delete gamer;
cout << frameCount / ((timeGetTime() - startTime) / 100) << " fps " << endl;
cout << "Game Over" << endl;
return true;
}
bool Runner::getInput(char *c)
{
if (kbhit())
{
*c = getch();
return true;
}
}
void Runner::timerUpdate()
{
double currentTime = timeGetTime() - lastTime;
if (currentTime < GAME_SPEED)
return;
frameCount++;
lastTime = timeGetTime();
}
game.h
#ifndef GAME_H
#define GAME_H
#include "drawEngine.h"
#include "Sprite.h"
#include "Character.h"
#include "level.h"
class Runner
{
public:
bool run();
Runner(){};
protected:
bool getInput(char *c);
void timerUpdate();
private:
Level *level;
Character* gamer;
double frameCount;
double startTime;
double lastTime;
int posX;
drawEngine drawArea;
};
#endif
drawEngine.cpp
#include <iostream>
#include "drawEngine.h"
#include <windows.h>
using namespace std;
drawEngine::drawEngine(int index, int xSize, int ySize, int x, int y)
{
screenWidth = x;
screenHeight = y;
map = 0;
//set cursor visibility to false
//cursorVisibility(false);
}
drawEngine::~drawEngine()
{
cursorVisibility(true);
//set cursor visibility to true
}
int drawEngine::createSprite(int index, char c)
{
if (index >= 0 && index < 16)
{
spriteImage[index] = c;
return index;
}
return -1;
}
void drawEngine::deleteSprite(int index)
{
// in this implemantation we don't need it
}
void drawEngine::drawSprite(int index, int posX, int posY)
{
//go to the correct location
gotoxy (index, posX, posY);
// draw the sprite
cout << spriteImage[index];
cursorVisibility(false);
}
void drawEngine::eraseSprite(int index, int posX, int posY)
{
gotoxy (index, posX, posY);
cout << ' ';
}
void drawEngine::setMap(char **data)
{
map = data;
}
void drawEngine::createBackgroundTile(int index, char c)
{
if (index >= 0 && index < 16)
{
tileImage[index] = c;
}
}
void drawEngine::drawBackground(void)
{
if(map)
{
for(int y = 0; y < screenHeight; y++)
{
gotoxy(0,y, 0);
for(int x = 0; x < screenWidth; x++)
cout << tileImage[map[x][y]];
}
}
}
void drawEngine::gotoxy(int index, int x, int y)
{
HANDLE output_handle;
COORD pos;
pos.X = x;
pos.Y = y;
output_handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output_handle, pos);
}
void drawEngine::cursorVisibility(bool visibility)
{
HANDLE output_handle;
CONSOLE_CURSOR_INFO cciInfo;
cciInfo.dwSize = 1;
cciInfo.bVisible = visibility;
output_handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorInfo(output_handle, &cciInfo);
}
drawEngine.h
#ifndef DRAWENGINE_H
#define DRAWENGINE_H
class drawEngine
{
public:
drawEngine(int index, int xSize = 30, int ySize = 20, int x = 0, int y = 0);
~drawEngine();
drawEngine(){};
int createSprite(int index, char c);
void deleteSprite(int index);
void eraseSprite(int index, int posX, int posY);
void createBackgroundTile(int index, char c);
void drawSprite(int index, int posX, int posY);
void drawBackground(void);
void setMap(char **);
protected:
char **map;
int screenWidth, screenHeight;
char spriteImage[16];
char tileImage[16];
private:
void gotoxy(int index, int x, int y);
void cursorVisibility(bool visibility);
};
#endif
I've also got Sprite.cpp, Sprite.h, Character.h,Character.cpp and main.cpp if you need them
Ok, I made it through the code and found one issue. The Runner class encapsulates a drawEngine object. At the constructor of Runner, the default c'tor of drawEngine is called, which doesn't set values for sceenWidth and screenHeight (or any other member). Luckily in debug mode, they are defaulted to 0xcccccccc which is negative so you're drawBackground returns immediately (Visual Studio 2010).
You should change that c'tor (or even remove it) and corretly initialize the engine in runner's constructor, e.g.:
class Runner {
public:
Runner() : drawArea(0, width, height, ?, ?){};
[...]
};
Further, the x and y members are used in the loops in drawBackground. You should use screenWidth and screenWidth, resp. BTW, I don't know what x and y should be in drawEngine
UPDATE: The x and y coordinates at the gotoxy call in drawBackground are mixed up, so you draw everything on the same line. BTW: what is index used for?