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.
Related
I am making a google chrome dinosaur game using an SDL Template for graphics and I am almost finished but I have run into the issue of needing to be able to reset to the starting values of the game just like how you reset when you hit spacebar after dying in the google chrome dinosaur game. I have made an isGameOver function but I don't know how to reset the values to start a new game which is my main problem.
this is my GameScene class where the game over logic is located
GameScene.h
#pragma once
#include "Scene.h"
#include "GameObject.h"
#include "Player.h"
#include "Floor.h"
#include "Obstacle.h"
#include "FlyingObstacle.h"
#include <vector>
#include "util.h"
#include "text.h"
class GameScene : public Scene
{
public:
GameScene();
~GameScene();
void start();
void draw();
void update();
std::vector<Obstacle*> spawnedObstacle;
std::vector<FlyingObstacle*> spawnedBird;
private:
Player* player;
Floor* floor;
float spawnTime;
float currentSpawnTimer;
void floorCollision();
void obstacleCollision();
void birdCollision();
void obstacleSpawn();
void birdSpawn();
void despawnObstacle(Obstacle* obstacle);
void despawnBird(FlyingObstacle* bird);
int points;
int highscore;
bool isGameOver;
};
GameScene.cpp
#include "GameScene.h"
GameScene::GameScene()
{
// Register and add game objects on constructor
player = new Player();
this->addGameObject(player);
floor = new Floor();
this->addGameObject(floor);
points = 0;
highscore = 0;
}
GameScene::~GameScene()
{
delete player;
}
void GameScene::start()
{
Scene::start();
// Initialize any scene logic here
initFonts();
isGameOver = true;
currentSpawnTimer = 300;
spawnTime = rand() % 300; //spawn time of 5 seconds
for (int i = 0; i < 1; i++)
{
obstacleSpawn();
}
for (int i = 0; i < 3; i++)
{
birdSpawn();
}
}
void GameScene::draw()
{
Scene::draw();
drawText(110, 20, 255, 255, 255, TEXT_CENTER, "POINTS: %03d", points);
if (player->getIsAlive() == true)
{
drawText(900, 20, 255, 255, 255, TEXT_CENTER, "PRESS SPACE TO START MOVING");
}
if (player->getIsAlive() == false)
{
if (isGameOver == false)
drawText(SCREEN_WIDTH / 2, 200, 255, 255, 255, TEXT_CENTER, "YOU LOSE! PRESS SPACE TO SHOW POINTS");
if (isGameOver == true)
{
drawText(SCREEN_WIDTH / 2, 200, 255, 255, 255, TEXT_CENTER, "HIGHSCORE: %03d", highscore);
if (points > highscore)
{
drawText(SCREEN_WIDTH / 2, 200, 255, 255, 255, TEXT_CENTER, "NEW HIGHSCORE: %03d", points, highscore);
}
}
}
}
void GameScene::update()
{
if (isGameOver == true)
{
if (app.keyboard[SDL_SCANCODE_SPACE])
{
isGameOver = false;
}
}
if (isGameOver == false)
{
Scene::update();
floorCollision();
obstacleCollision();
birdCollision();
if (currentSpawnTimer > 0)
currentSpawnTimer--;
if (currentSpawnTimer <= 0)
{
for (int i = 0; i < 1; i++)
{
obstacleSpawn();
}
for (int i = 0; i < 3; i++)
{
birdSpawn();
}
currentSpawnTimer = spawnTime;
}
//This is where Gravity strength is located
if (player->getOnFloor() == false) {
player->setY(player->getY() + 7);
}
else {
player->getY() + 0;
}
}
}
void GameScene::floorCollision()
{
//Checks for collisions
for (int i = 0; i < objects.size(); i++)
{
//Cast to floor
Floor* floor = dynamic_cast<Floor*>(objects[i]);
//Check if the floor was casted
if (floor != NULL)
{
int collision = checkCollision(
player->getX(), player->getY(), player->getWidth(), player->getHeight(),
floor->getX(), floor->getY(), floor->getWidth(), floor->getHeight()
);
if (collision == 1)
{
player->setOnFloor(true);
if (player->getIsAlive() == true)
{
points++;
highscore++;
}
break;
}
}
}
}
void GameScene::obstacleCollision()
{
for (int i = 0; i < objects.size(); i++)
{
Obstacle* obstacle = dynamic_cast<Obstacle*>(objects[i]);
if (obstacle != NULL)
{
if (obstacle != NULL)
{
int collision = checkCollision(
player->getX(), player->getY(), player->getWidth(), player->getHeight(),
obstacle->getX(), obstacle->getY(), obstacle->getWidth(), obstacle->getHeight()
);
if (collision == 1)
{
player->doDeath();
isGameOver = true;
break;
}
}
}
}
}
void GameScene::birdCollision()
{
for (int i = 0; i < objects.size(); i++)
{
FlyingObstacle* bird = dynamic_cast<FlyingObstacle*>(objects[i]);
if (bird != NULL)
{
if (bird != NULL)
{
int collision = checkCollision(
player->getX(), player->getY(), player->getWidth(), player->getHeight(),
bird->getX(), bird->getY(), bird->getWidth(), bird->getHeight()
);
if (collision == 1)
{
player->doDeath();
isGameOver = true;
break;
}
}
}
}
}
void GameScene::obstacleSpawn()
{
Obstacle* obstacle = new Obstacle();
this->addGameObject(obstacle);
obstacle->setPosition(1200, 300 + (rand() % 300));
spawnedObstacle.push_back(obstacle);
}
void GameScene::birdSpawn()
{
FlyingObstacle* bird = new FlyingObstacle();
this->addGameObject(bird);
bird->setPos(1200, 300 + (rand() % 300));
spawnedBird.push_back(bird);
}
void GameScene::despawnObstacle(Obstacle* obstacle)
{
int index = -1;
for (int i = 0; i < spawnedObstacle.size(); i++)
{
//If pointer matches
if (obstacle == spawnedObstacle[i])
{
index = i;
break;
}
}
//If any match is found
if (index != -1)
{
spawnedObstacle.erase(spawnedObstacle.begin() + index);
delete obstacle;
}
}
void GameScene::despawnBird(FlyingObstacle* bird)
{
int index = -1;
for (int i = 0; i < spawnedBird.size(); i++)
{
//If pointer matches
if (bird == spawnedBird[i])
{
index = i;
break;
}
}
//If any match is found
if (index != -1)
{
spawnedBird.erase(spawnedBird.begin() + index);
delete bird;
}
}
I tried making an isGameOver bool inside my GameScene.h and I made it so that pressing spacebar would reset the game but in reality when the player dies the screen pauses every movement instead of resetting and if I press space again the game continues to move even though the player is dead.
Your entry point for the game(probably main function will probably have some form like this)
#include ...
#include ...
...
int main()
{
bool game_running = true;
while(game_running)
{
GameInstance* game = new Game(); //Allocation and initialization of all resources needed to play the game.
game.play(); // This function will finish when you lose the game.
delete game; // Deallocation.
if(!run_again())
{
game_running = false;
}
}
return 0;
}
After deallocation, you check if user wants to play again, you enter the next iteration of while loop, and new instance of Game is allocated, where all the resource handling takes place. The only problem is that allocating Game instance for every iteration might be a little costly, but you can ignore that if you don't worry about performance much.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am really struggling with that strange bug for some time. My application crashes even before widgets are shown (but window itself is shown). Here is my code:
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.setWindowTitle("Snake");
w.resize(500, 500);
w.show();
QTimer* timer = new QTimer();
while(!w.checkCollision())
{
if(timer -> isActive() == false)
{
w.play();
timer -> start(1);
}
}
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPainter>
#include <QKeyEvent>
#include <QDebug>
#include <snakeclass.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
Snake snake;
void paintEvent(QPaintEvent*);
void keyEvent(QKeyEvent* keyevent);
void move();
bool checkCollision();
void play();
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QPainterPath>
#include <QKeyEvent>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
}
void MainWindow::paintEvent(QPaintEvent*)
{
QPainter painter(this);
// Draw black background.
painter.drawRect(0, 0, 500, 500);
painter.fillRect(0, 0, 500, 500, Qt::black);
for(unsigned int i = 0; i < snake.getLength(); i++)
{
// Draw green snake's body.
painter.setPen(Qt::green);
painter.setBrush(Qt::green);
// If i = 0, so if we are drawing snake's head.
if(i == 0)
{
// Draw red head.
painter.setPen(Qt::red);
painter.setBrush(Qt::red);
}
painter.drawEllipse((snake.getDot(i)).x, (snake.getDot(i)).y, 10, 10);
}
}
void MainWindow::keyEvent(QKeyEvent* keyevent)
{
if(keyevent -> key() == Qt::Key_Left)
{
if(snake.getDirection() != Snake::Direction::RIGHT)
{
snake.setDirection(Snake::Direction::LEFT);
}
}
else if(keyevent -> key() == Qt::Key_Right)
{
if(snake.getDirection() != Snake::Direction::LEFT)
{
snake.setDirection(Snake::Direction::RIGHT);
}
}
else if(keyevent -> key() == Qt::Key_Up)
{
if(snake.getDirection() != Snake::Direction::DOWN)
{
snake.setDirection(Snake::Direction::UP);
}
}
else if(keyevent -> key() == Qt::Key_Down)
{
if(snake.getDirection() != Snake::Direction::UP)
{
snake.setDirection(Snake::Direction::DOWN);
}
}
}
void MainWindow::move()
{
for(unsigned int i = snake.getLength(); i > 0; i--)
{
snake.editDot((snake.getDot(i - 1)).x, (snake.getDot(i - 1)).y, i, (snake.getDot(i - 1)).direction);
}
if(snake.getDirection() == Snake::Direction::UP)
{
if(int(snake.getDot(0).y - 10) < 0)
{
snake.editDot((snake.getDot(0)).x, 500, 0, snake.getDirection());
}
else
{
snake.editDot((snake.getDot(0)).x, (snake.getDot(0)).y - 10, 0, snake.getDirection());
}
}
else if(snake.getDirection() == Snake::Direction::DOWN)
{
if(((snake.getDot(0)).y + 10) > 490)
{
snake.editDot((snake.getDot(0)).x, 0, 0, snake.getDirection());
}
else
{
snake.editDot((snake.getDot(0)).x, (snake.getDot(0)).y + 10, 0, snake.getDirection());
}
}
else if(snake.getDirection() == Snake::Direction::RIGHT)
{
if(((snake.getDot(0)).x + 10) > 490)
{
snake.editDot(0, (snake.getDot(0)).y, 0, snake.getDirection());
}
else
{
snake.editDot((snake.getDot(0)).x + 10, (snake.getDot(0)).y, 0, snake.getDirection());
}
}
else if(snake.getDirection() == Snake::Direction::LEFT)
{
if((int((snake.getDot(0)).x) - 10) < 0)
{
snake.editDot(500, (snake.getDot(0)).y, 0, snake.getDirection());
}
else
{
snake.editDot((snake.getDot(0)).x - 10, (snake.getDot(0)).y, 0, snake.getDirection());
}
}
}
bool MainWindow::checkCollision()
{
for(unsigned int i = 0; i < snake.getLength(); i++)
{
for(unsigned int j = 0; j < snake.getLength(); j++)
{
if((i != j) && ((snake.getDot(i)).x == (snake.getDot(j)).x) && ((snake.getDot(i)).y == (snake.getDot(j)).y))
{
return true;
}
}
}
return false;
}
void MainWindow::play()
{
//move();
update();
}
MainWindow::~MainWindow()
{
delete ui;
}
snakeclass.h
#ifndef SNAKECLASS
#define SNAKECLASS
#include <vector>
class Snake
{
public:
enum class Direction
{
LEFT,
RIGHT,
UP,
DOWN
};
// Dot is a part of the snake.
struct dot
{
unsigned int x;
unsigned int y;
// Number of the dot (head is 0).
unsigned int dotNumber;
// Direction of the particular dot.
Direction direction;
};
unsigned int getLength();
unsigned int getScore();
unsigned int getSpeed();
Direction getDirection();
dot getDot(unsigned int dotNumber);
void setLength(unsigned int length);
void setScore(unsigned int score);
void setSpeed(unsigned int speed);
void setDirection(Direction direction);
// Returns new dot's dotNumber.
unsigned int newDot();
void editDot(unsigned int x, unsigned int y, unsigned int dotNumber, Direction direction);
private:
unsigned int length = 3;
unsigned int score = 0;
unsigned int speed = 1;
Direction direction = Direction::RIGHT;
std::vector <dot> dots = {dot {250, 250, 0, Direction::RIGHT},
dot {240, 250, 1, Direction::RIGHT},
dot {230, 250, 2, Direction::RIGHT}};
};
#endif // SNAKECLASS
snakeclass.cpp
#include "snakeclass.h"
unsigned int Snake::getLength()
{
return length;
}
unsigned int Snake::getScore()
{
return score;
}
unsigned int Snake::getSpeed()
{
return speed;
}
Snake::Direction Snake::getDirection()
{
return direction;
}
Snake::dot Snake::getDot(unsigned int dotNumber)
{
return dots.at(dotNumber);
}
void Snake::setLength(unsigned int length)
{
this -> length = length;
}
void Snake::setScore(unsigned int score)
{
this -> score = score;
}
void Snake::setSpeed(unsigned int speed)
{
this -> speed = speed;
}
void Snake::setDirection(Snake::Direction direction)
{
this -> direction = direction;
}
unsigned int Snake::newDot()
{
dot newDot;
newDot.dotNumber = dots.size();
dots.push_back(newDot);
length ++;
return newDot.dotNumber;
}
void Snake::editDot(unsigned int x, unsigned int y, unsigned int dotNumber, Snake::Direction direction)
{
for(unsigned int i = 0; i < dots.size(); i++)
{
if((dots.at(i)).dotNumber == dotNumber)
{
dots.at(i).x = x;
dots.at(i).y = y;
dots.at(i).direction = direction;
}
}
}
I am new to Qt5 and this is my first project involving painter and keyboard events. Could you help me to figure out what the problem in the code above is? Thank you for all the answers!
My application crashes even before widgets are shown (but window itself is shown).
It doesn't crash. In main.cpp there is an infinite loop in which some results are expected, namely !w.checkCollision(), but since there is no event loop running in main.cpp nothing happens and the programs hangs there waiting in vain.
As an answer to your question, in order to see the widgets add QApplication::processEvents(); in the following way:
while(!w.checkCollision())
{
QApplication::processEvents();
if(timer -> isActive() == false)
{
w.play();
timer -> start(1);
}
}
However, with this approach you will face further problems. So I would strongly advise you to take a look at the examples in the Qt Creator in order to see which is the correct way of using the library as thought by the Qt developers.
So I am trying to make a chessgame, and of course I am starting out with just making the board. For this I am creating a two-dimensional array like 8x8. Each tile has their own object sprite called tileSprite and I am trying to define them as 1/8th of the width and height of the screen, which has a fixed size of 1024x768. The textures that are loaded in are just 1 pixel black or white. The program gives no definitive error, but the drawn tiles aren't getting displayed onto my window, and all I see is a red screen, which I get from clearing the screen (following the standard clear/draw/display cycle of SFML).
#include "SFML/Window.hpp"
#include "SFML/Graphics.hpp"
#include "SFML/Audio.hpp"
#include <iostream>
#include <vector>
#include <array>
bool playing = true;
class Textures {
public:
static void loadTextures();
sf::Texture static blackTile;
sf::Texture static whiteTile;
};
/*---Class--Definitions----*/
sf::Texture Textures::blackTile;
sf::Texture Textures::whiteTile;
/*-------------------------*/
void Textures::loadTextures() {
if (blackTile.loadFromFile("Images/blackTile.PNG")) {
return;
}
else if (whiteTile.loadFromFile("Images/whiteTile.PNG")) {
return;
}
}
class ChessBoard_Tiles {
public:
static void _initialize();
static void draw(sf::RenderWindow& window);
enum TileStatus { EMPTY, OCCUPIED, HIGHLIGHTED };
struct TileSlot {
sf::Sprite tileSprite;
TileStatus tileStatus;
};
private:
typedef std::array< std::array<TileSlot*, 8>, 8 > TileType;
static TileType tileBoard;
};
/*-Class Definition that has to be called-*/
ChessBoard_Tiles::TileType ChessBoard_Tiles::tileBoard = ChessBoard_Tiles::TileType();
void ChessBoard_Tiles::_initialize() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
tileBoard[i][j] = new TileSlot();
if ((i + j) % 2 == 0) {
tileBoard[i][j]->tileSprite.setTexture(Textures::whiteTile);
}
else {
tileBoard[i][j]->tileSprite.setTexture(Textures::blackTile);
}
tileBoard[i][j]->tileSprite.setPosition(128 * j, 96 * i);
tileBoard[i][j]->tileSprite.setScale(128, 96);
tileBoard[i][j]->tileStatus = EMPTY;
}
}
}
void ChessBoard_Tiles::draw(sf::RenderWindow& window) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
window.draw(tileBoard[i][j]->tileSprite);
}
}
}
int main(int argc, char* argv[]) {
sf::RenderWindow renderWindow;
renderWindow.create(sf::VideoMode(1024, 768), "Chess");
Textures::loadTextures();
ChessBoard_Tiles::_initialize();
while (playing) {
sf::Event currentEvent;
renderWindow.pollEvent(currentEvent);
if (currentEvent.type == sf::Event::Closed) {
renderWindow.close();
playing = false;
}
if (currentEvent.type == sf::Event::KeyPressed) {
if (currentEvent.key.code == sf::Keyboard::Escape) {
renderWindow.close();
playing = false;
}
}
renderWindow.clear(sf::Color::Red);
std::cout << "Clear\n";
ChessBoard_Tiles::draw(renderWindow);
std::cout << "Draw\n";
renderWindow.display();
std::cout << "Display\n";
}
return 0;
}
If anyone knows what is wrong then that would be a big help for me.. Otherwise I'd probably have to entirely remake this program, which I think should work so far, but I haven't the slightest idea why it doesn't. Big thanks in advance =)
EDIT: Read a little about how the sprites seem to disappear if the textures are running out of scope.. If this is the case, could that just be pointed out and then I can work on that, because I have tried so many different things by now that I feel like I'm just going in circles?
The fault was from the loadTextures() function, where I had forgotten to include the file extension of the file to be loaded, and I screwed the logic about the loadFromFile() function up so the program only continued when it couldn't load the file..
I have a problem with SDL. As you see, I have 3 files: include.h, map.h, source.cpp.
In include.h I included all libraries.
In map.h I wrote a class: getTileID reads a picture and slices it to tiles, getTilePosition reads .txt file, drawMap function makes a surface assigning sliced surface tiles to id values from text file.
Then, in source.cpp I initiliaze SDL, SetVideoMode, and create a class A. After that, I call class A functions. After calling it, I A.mapSurface[0] variable to screen and flip it.
Nothing happens. Screen loads, and, as I think it flips with empty surface, but it needs to display mapSurface variable.
Please help.
//include.h
//----------------------------------------------------------------------------------------------------
#include "headers\SDL.h"
#include "headers\SDL_image.h"
//----------------------------------------------------------------------------------------------------
#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")
#pragma comment(lib, "SDL_image.lib")
//----------------------------------------------------------------------------------------------------
#include <string>
#include <fstream>
//----------------------------------------------------------------------------------------------------
#include "map.h"
-
//map.h
//----------------------------------------------------------------------------------------------------
#pragma once
//#include "include.h"
//----------------------------------------------------------------------------------------------------
class map
{
public:
//----------------------------------------------------------------------------------------------------
map(void);
~map(void);
void getTileID(const char* mapFile);
void getTilePosition(std::string mapFile);
void drawMap();
//----------------------------------------------------------------------------------------------------
static const short int TILEMAP_WIDTH = 24;
static const short int TILEMAP_HEIGHT = 24;
static const short int TILE_WIDTH = 32;
static const short int TILE_HEIGHT = 32;
SDL_Surface* tileID[1025];
short int mapWidth;
short int mapHeight;
short int mapID[2][500][500];
short int graphicLayer;
SDL_Surface* mapSurface[5];
};
//----------------------------------------------------------------------------------------------------
map::map(void)
{
}
map::~map(void)
{
}
//----------------------------------------------------------------------------------------------------
void map::getTileID(const char* mapFile)
{
IMG_Init(IMG_INIT_PNG);
SDL_Surface *tileMap;
tileMap = IMG_Load(mapFile);
if(tileMap == NULL)
{
exit(1);
}
for(short int i = 0; i < map::TILEMAP_WIDTH * map::TILEMAP_HEIGHT + 1; i++)
{
map::tileID[i] = (SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA, map::TILE_WIDTH, map::TILE_HEIGHT, 32, 0, 0, 0, 0));
if(map::tileID[i] == NULL)
{
exit(2);
}
}
tileID[0] = NULL;
short int id = 1;
for(short int c = 0; c < map::TILEMAP_WIDTH; c++)
{
for(short int r = 0; r < map::TILEMAP_HEIGHT; r++)
{
short int sliceX = c * map::TILE_WIDTH;
short int sliceY = r * map::TILE_HEIGHT;
SDL_Rect srcRect;
srcRect.x = sliceX;
srcRect.y = sliceY;
srcRect.w = map::TILE_WIDTH;
srcRect.h = map::TILE_HEIGHT;
SDL_Rect dstRect;
dstRect.x = 0;
dstRect.y = 0;
dstRect.h = 32;
dstRect.w = 32;
if(SDL_BlitSurface(tileMap, &srcRect, map::tileID[id], &dstRect) != NULL)
exit(3);
id++;
}
}
SDL_FreeSurface(tileMap);
IMG_Quit();
}
//----------------------------------------------------------------------------------------------------
void map::getTilePosition(std::string mapFile)
{
std::string
tag,
objType[10];
short int
l = 0;
float
objX[10],
objY[10],
objWidth[10],
objHeight[10];
std::ifstream data(mapFile);
while(!data.eof())
{
getline(data, tag);
if(tag == "[header]")
{
data.ignore(256, '=');
data >> map::mapWidth;
data.ignore(256, '=');
data >> map::mapHeight;
data.ignore(256, '\n');
}
map::graphicLayer = 0;
if(tag == "[layer]")
{
data.ignore(256, '\n');
data.ignore(256, '\n');
for(short int c = 0; c < map::mapHeight; c++)
{
for(short int r = 0; r < map::mapWidth; r++)
{
data >> map::mapID[map::graphicLayer][c][r];
}
}
map::graphicLayer++;
data.ignore(256, '\n');
}
if(tag.substr(0, 7) == "[object")
{
objType[l] = tag.substr(8, tag.size() - 9);
data.ignore(256, '\n');
data.ignore(256, '\n');
data.ignore(256, '=');
data >> objX[l] >> objY[l] >> objWidth[l] >> objHeight[l];
l++;
data.ignore(256, '\n');
}
}
data.close();
}
//----------------------------------------------------------------------------------------------------
void map::drawMap()
{
map::mapSurface[0] = (SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA, 3200 ,3200 , 32, 255, 255, 255, 0));
for(short int gl = 0; gl < map::graphicLayer; gl++)
{
for(short int c = 0; c < map::mapWidth; c++)
{
for(short int r = 0; r < map::mapHeight; r++)
{
for(short int id = 0; id < map::TILEMAP_WIDTH * map::TILEMAP_HEIGHT; id++)
{
if(map::mapID[gl][c][r] == id)
{
SDL_Rect dstRect;
dstRect.x = c * map::TILE_WIDTH;
dstRect.y = r * map::TILE_HEIGHT;
if(SDL_BlitSurface(map::tileID[id], NULL, map::mapSurface[gl], &dstRect) != NULL)
exit(4);
}
}
}
}
}
}
-
//source.cpp
//----------------------------------------------------------------------------------------------------
#include "../libraries/include.h"
//----------------------------------------------------------------------------------------------------
int main(int argc,char *argv[])
{
if(SDL_Init(SDL_INIT_EVERYTHING) != NULL)
exit(0);
SDL_Surface *screen;
screen = SDL_SetVideoMode(1024, 768, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
map A;
A.getTileID("map.png");
A.getTilePosition("map.txt");
A.drawMap();
screen = A.mapSurface[0];
SDL_Flip(screen);
SDL_Delay(1000);
SDL_FreeSurface(screen);
SDL_Quit();
return 0;
}
It looks like you are drawing your map to map::mapSurface[0] but this surface is never drawn to the screen. Blit your temporary surface to screen after drawMap or draw directly to the screen.
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?