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;
Related
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.
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 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.
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?
Hi I am having trouble with my code. I got error C2227.
My code:
Game.h
#ifndef GAME_H
#define GAME_H
#include "drawEngine.h"
#include "Sprite.h"
class Runner
{
public:
bool run();
Runner(){};
protected:
bool getInput(char *c);
void timerUpdate();
private:
int *gamer;
double frameCount;
double startTime;
double lastTime;
int posX;
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()
{
drawArea.createSprite(0, '$');
gamer; new Character(&drawArea, 0);
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();
}
I've never seen this before.
I've looked everywhere for an answer but they don't work with my code. I've got other code too that belongs to the same project which I didn't post.
I think the problem is that you've defined gamer as
int *gamer;
So when you write
gamer->keyPress(key);
You're trying to call a member function on an int, which is not legal.
Are you sure you want gamer to be an int *? That seems incorrect.
Change
int *gamer;
to
Character* gamer;
and
gamer; new Character(&drawArea, 0);
to
gamer = new Character(&drawArea, 0);