Transfer a 2D array to a csv file? - c++

I have a matrix called "temp_matrix" that looks kind of like this:
0.0,100.0,100.0,100.0,
0.0,45.1,60.6,66.2,0,
0.0,45.1,60.6,66.2,0,
0.0,100.0,100.0,100.0,0,
...except mine is a 20x20 matrix.
I've tried:
ofstream excel_plate("plate.csv");
excel_plate.write(temp_matrix[0],20);
excel_plate.close();
cout << endl;
but can't compile.
I've tried:
ofstream excel_plate("plate.csv");
excel_plate << temp_matrix[0], 20, 20;
excel_plate.close();
...but just get a csv file with a string of characters in the very first cell that looks like this: 0052EE98.
Here is my code:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <math.h>
#include <Windows.h>
#include <algorithm>
#include <string>
#include <array>
#undef max
using namespace std;
const double neighbors = 4;
// START FUNCTION: Update Elements
void average(double *temp_matrix, int ROWS, int COLUMNS)
{
int i = 0;
int j = 0;
double row_left = 0;
double row_right = 0;
double column_up = 100;
double column_down = 0;
double sum = 0;
double av = 0;
for (int i = 1; i < ROWS - 1; i++)
{
for (int j = 1; j < COLUMNS - 1; j++)
{
/*
cout << "row_left:" << *(temp_matrix + i*ROWS + (j - 1)) << " ";
cout << "row_right:" << *(temp_matrix + i*ROWS + (j + 1)) << " ";
cout << "column_up:" << *(temp_matrix + (i - 1)*ROWS + j) << " ";
cout << "column_down:" << *(temp_matrix + (i + 1)*ROWS + j) << " ";
*/
row_left = *(temp_matrix + i*ROWS + (j-1));
row_right = *(temp_matrix + i*ROWS + (j + 1));
column_up = *(temp_matrix + (i-1)*ROWS + j);
column_down = *(temp_matrix + (i+1)*ROWS + j);
sum = row_left + row_right + column_up + column_down;
av = sum / neighbors;
*(temp_matrix + i*ROWS + j) = av;
}
}
}
// END FUNCTION: Update Elements
// START FUNCTION: Updtate Until Stable
void update(double *temp_matrix, int ROWS, int COLUMNS)
{
int i = 0;
int j = 0;
double row_left = 0;
double row_right = 0;
double column_up = 100;
double column_down = 0;
double sum = 0;
double old_num = 0;
double new_num = 0;
double difference = 0;
double max_change = .11;
while (max_change > .1)
{
max_change = -1;
for (int i = 1; i < ROWS - 1; i++)
{
for (int j = 1; j < COLUMNS - 1; j++)
{
old_num = *(temp_matrix + i*ROWS + j);
/*
cout << "row_left:" << *(temp_matrix + i*ROWS + (j - 1)) << " ";
cout << "row_right:" << *(temp_matrix + i*ROWS + (j + 1)) << " ";
cout << "column_up:" << *(temp_matrix + (i - 1)*ROWS + j) << " ";
cout << "column_down:" << *(temp_matrix + (i + 1)*ROWS + j) << " ";
*/
row_left = *(temp_matrix + i*ROWS + (j - 1));
row_right = *(temp_matrix + i*ROWS + (j + 1));
column_up = *(temp_matrix + (i - 1)*ROWS + j);
column_down = *(temp_matrix + (i + 1)*ROWS + j);
sum = row_left + row_right + column_up + column_down;
new_num = sum / neighbors;
difference = new_num - old_num;
if (difference > max_change)
{
max_change = difference;
}
*(temp_matrix + i*ROWS + j) = new_num;
}
}
}
}
// END FUNCTION: Update Until Stable
// START FUNCTION: Print Array
void print_array(double *temp_matrix, int ROWS, int COLUMNS)
{
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLUMNS; j++)
{
if (j > 0)
{
cout << ",";
}
cout << fixed << setw(5) << setprecision(1) << *(temp_matrix + i*ROWS + j);
}
cout << endl;
}
}
// END FUNCTION: Print Array
// START FUNCTION: Print 4 Excel
void print_excel(double *temp_matrix, int ROWS, int COLUMNS)
{
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLUMNS; j++)
{
cout << fixed << setprecision(1) << *(temp_matrix + i*ROWS + j) << ",";
}
cout << endl;
}
}
// END FUNCTION: Print 4 Excel
int main()
{
const int ROWS = 20;
const int COLUMNS = 20;
double temp_matrix[ROWS][COLUMNS] =
{
{ 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 0 }
};
print_array(temp_matrix[0], 20, 20);
system("pause");
cout << endl << endl;
average(temp_matrix[0], 20, 20);
print_array(temp_matrix[0], 20, 20);
system("pause");
cout << endl << endl;
update(temp_matrix[0], 20, 20);
print_array(temp_matrix[0], 20, 20);
system("pause");
cout << endl << endl;
print_excel(temp_matrix[0], 20, 20);
ofstream excel_plate("plate.csv");
if (excel_plate.is_open())
{
excel_plate << temp_matrix[0], 20, 20;
excel_plate.close();
}
else
{
cout << "Unable to open file.";
}
/*
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLUMNS; j++)
{
if (j > 0)
{
cout << ",";
}
cout << temp_matrix[i][j];
}
cout << endl;
}
*/
system("pause");
return 0;
}
This should be very, very simple. Please kindly help a noob out. :)
P.S. Because this is an assignment, you'll notice that I print out several matrices. The last one I print out is the format in which the matrix needs to be transferred to a .csv file.

The simplest way would be something like the following (assuming you can use c++11)
std::ofstream out("test.csv");
for (auto& row : temp_matrix) {
for (auto col : row)
out << col <<',';
out << '\n';
}

So, this code conatains a functions that should be able to transfer any 2d string array into a csv file
#include <iostream>
#include <fstream>
#include<string>
/* This is for a string array, but if you want to use any other type, just replace
'std::string' with int,double....*/
template <size_t row, size_t col>
void twodarray2csv(std::string(&array)[row][col], std::string filename)
{
std::ofstream myfile;
myfile.open(filename);
for (size_t i = 0; i < row; ++i)
{
for (size_t j = 0; j < col; ++j)
if (j < (col - 1)) {
myfile << array[i][j] << ",";
}
else if (j == (col - 1)) {
myfile << array[i][j] << "\n";
}
}
}
Th template gets the row size and column size and also opens ofstream which is basically for just opening the csv file that will be the output file
int main() {
//example
std::string ArrayName[9][3];
/* this for loop is just there to populate the array, if you have an array
already skip this step */
#include <iostream>
#include <fstream>
#include<string>
/* This is for a string array, but if you want to use any other type, just replace
'std::string' with int,double....*/
template <size_t row, size_t col>
void twodarray2csv(std::string(&array)[row][col], std::string filename)
{
std::ofstream myfile;
myfile.open(filename);
for (size_t i = 0; i < row; ++i)
{
for (size_t j = 0; j < col; ++j)
if (j < (col - 1)) {
myfile << array[i][j] << ",";
}
else if (j == (col - 1)) {
myfile << array[i][j] << "\n";
}
}
}
So the function above uses a template to get the row size and column size of the array, after which it iterates through the array so that when it passes by elements of the same row it adds a comma to the file and at the end of each row it adds a new line (\n) which is a row separator
The part below is an example of how to use it and how it works
First i just created a an Array called ArrayName, and populated it with just some numbers (int number)
int number = 0;
for (int i = 0; i < 9; i++) {
for (int x = 0; x < 3; x++) {
ArrayName[i][x] = number;
number++;
}
}
//this part converts the array to a csv file of desried name
twodarray2csv(ArrayName, "outputfile.csv");
return 0;
}
The output will be a csv file with the name "outputfile.csv" stored in the same folder with the cpp file you have

Related

Unable to get BFS algorithm to work properly in c++

I'm creating a dungeon/rouge-like game in c++ and am trying to implement pathfinding.
The issue I am having is that when the player moves more than two times the adjacency matrix doesn't generate properly. What happens is that every place that the player has been turning to a zero which signifies that you cant go there. I am trying to regenerate the matrix every time the player moves but it doesn't seem to want to. here is the code.
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
int World_Width = 10;
int World_Height = 10;
int Player_X = 1;
int Player_Y = 2;
int Enemy_X = 8;
int Enemy_Y = 1;
int X = Player_X;
int Y = Player_Y;
int Player_Health = 10;
int Enemy_Health = 5;
int Player_Damage = 1;
int Enemy_Damage = 1;
bool PlayerIsAlive = true;
bool EnemyIsAlive = true;
int World[World_Width][World_Height] =
{
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 4, 1},
{1, 2, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 0, 1, 1, 0, 1, 0, 0, 1},
{1, 0, 0, 1, 1, 0, 1, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 1, 1, 1, 0, 0, 1, 0, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
int NodeMap[World_Width][World_Height] =
{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
};
int NeighborMap[World_Width][World_Height] =
{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
};
int NodeNumber = 1;
for (int h = 0; h < World_Height; h++)
{
for (int d = 0; d < World_Width; d++)
{
NodeMap[h][d] = NodeNumber;
NodeNumber ++;
}
}
vector<int> queue {};
vector<int> visited {};
string input;
bool AddNode = true;
int QueueNumber = 0;
int Max_iterations = 1000;
int TurnCount = 0;
bool run = true;
while (run)
{
TurnCount += 1;
//Prints out the map
for (int h = 0; h < World_Height; h++)
{
for (int d = 0; d < World_Width; d++)
{
cout << World[h][d] << " ";
}
cout << "\n";
}
cout << "\n";
cout << "Player health: " << Player_Health << "\n";
cout << "Enemy health: " << Enemy_Health << "\n" << "\n";
cout << "What do you want to do; move, attack, or open a chest: ";
//Player movement
cin >> input;
if (input == "w" && World[Player_Y - 1][Player_X] == 0)
{
World[Player_Y ][Player_X] = 0;
Player_Y--;
World[Player_Y][Player_X] = 2;
}
if (input == "a" && World[Player_Y][Player_X - 1] == 0)
{
World[Player_Y][Player_X] = 0;
Player_X--;
World[Player_Y][Player_X] = 2;
}
if (input == "s" && World[Player_Y + 1][Player_X] == 0)
{
World[Player_Y][Player_X] = 0;
Player_Y++;
World[Player_Y][Player_X] = 2;
}
if (input == "d" && World[Player_Y][Player_X + 1] == 0)
{
World[Player_Y][Player_X] = 0;
Player_X++;
World[Player_Y][Player_X] = 2;
}
if (input == "e")
{
if (Player_X == Enemy_X && Player_Y - 1 == Enemy_Y)
{
Enemy_Health -= Player_Damage;
}
if (Player_X == Enemy_X - 1 && Player_Y == Enemy_Y)
{
Enemy_Health -= Player_Damage;
}
if (Player_X == Enemy_X && Player_Y + 1 == Enemy_Y)
{
Enemy_Health -= Player_Damage;
}
if (Player_X == Enemy_X + 1 && Player_Y == Enemy_Y)
{
Enemy_Health -= Player_Damage;
}
}
if ( input == "stop")
{
Player_Health = 0;
}
queue.clear();
QueueNumber = 0;
X = Player_X;
Y = Player_Y;
NeighborMap[Y][X] = 0;
//BFS - Breadth First Search: Pathfinding Algorithim
for (int iterations = 0; iterations < Max_iterations; iterations++)
{
if (World[Y - 1][X] == 0 || World[Y - 1][X] == 4)
{
AddNode = true;
for (int i = 0; i < visited.size(); i++)
{
if (visited[i] == NodeMap[Y - 1][X])
{
AddNode = false;
}
}
if (AddNode)
{
queue.push_back(NodeMap[Y - 1][X]);
NeighborMap[Y - 1][X] = NodeMap[Y][X];
}
}
if (World[Y][X - 1] == 0 || World[Y][X - 1] == 4)
{
AddNode = true;
for (int i = 0; i < visited.size(); i++)
{
if (visited[i] == NodeMap[Y][X - 1])
{
AddNode = false;
}
}
if (AddNode)
{
queue.push_back(NodeMap[Y][X - 1]);
NeighborMap[Y][X - 1] = NodeMap[Y][X];
}
}
if (World[Y + 1][X] == 0 || World[Y + 1][X] == 4)
{
AddNode = true;
for (int i = 0; i < visited.size(); i++)
{
if (visited[i] == NodeMap[Y + 1][X])
{
AddNode = false;
}
}
if (AddNode)
{
queue.push_back(NodeMap[Y + 1][X]);
NeighborMap[Y + 1][X] = NodeMap[Y][X];
}
}
if (World[Y][X + 1] == 0 || World[Y][X + 1] == 4)
{
AddNode = true;
for (int i = 0; i < visited.size(); i++)
{
if (visited[i] == NodeMap[Y][X + 1])
{
AddNode = false;
}
}
if (AddNode)
{
queue.push_back(NodeMap[Y][X + 1]);
NeighborMap[Y][X + 1] = NodeMap[Y][X];
}
}
for (int h = 0; h < World_Height; h++)
{
for (int d = 0; d < World_Width; d++)
{
if(NodeMap[h][d] == queue[QueueNumber])
{
X = d;
Y = h;
}
}
}
visited.push_back(queue[QueueNumber]);
QueueNumber++;
}
//Enemy AI
if (Enemy_Health == 0)
{
if (EnemyIsAlive)
{
World[Enemy_Y][Enemy_X] = 0;
}
EnemyIsAlive = false;
}
if (Player_Health == 0)
{
run = false;
}
}
system("clear");
for (int h = 0; h < World_Height; h++)
{
for (int d = 0; d < World_Width; d++)
{
cout << NeighborMap[h][d] << " ";
}
cout << "\n";
}
cout << "\n";
for (int h = 0; h < World_Height; h++)
{
for (int d = 0; d < World_Width; d++)
{
cout << NodeMap[h][d] << " ";
}
cout << "\n";
}
cout << "GAME OVER" << "\n" << "Thanks for Playing!";
}

Create multiple objects for a simulation

Basically I wrote code to simulate one encoded data vector over a AWGN channel. The simulation but only works once. So I would like to create multiple objects or find a way to run the code multiple times depending on int N (for example int N = 1000000; in my case), so that I can calculate the BER (bit error rate).
I haven't found an elegant way to do that yet though...
I hope you understand my question.
Do you need more information?
Thank you!!
#include <iostream>
#include "encode.h"
#include "awgn.h"
#include "decode.h"
using namespace Eigen;
int main()
{
std::string code = "Hamming";
int dim_u, dim_mat_col, dim_mat_row, dim_mat_col_H, dim_mat_row_H;
MatrixXi P;
if (code == "Hamming")
{
dim_u = 4; // can also call it "k"
dim_mat_col = 7; // also serves as dim of x and y, or simply n
dim_mat_row = 4;
dim_mat_col_H = dim_mat_col;
dim_mat_row_H = dim_mat_col - dim_mat_row;
P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
P << 1, 1, 0,
0, 1, 1,
1, 1, 1,
1, 0, 1;
}
if (code == "BCH")
{
dim_u = 7;
dim_mat_col = 15; // also serves as dim of x and y, or simply n
dim_mat_row = 7;
dim_mat_col_H = dim_mat_col;
dim_mat_row_H = dim_mat_col - dim_mat_row;
P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
P << 1, 1, 1, 0, 1, 0, 0, 0,
0, 1, 1, 1, 0, 1, 0, 0,
0, 0, 1, 1, 1, 0, 1, 0,
0, 0, 0, 1, 1, 1, 0, 1,
1, 1, 1, 0, 0, 1, 1, 0,
0, 1, 1, 1, 0, 0, 1, 1,
1, 1, 0, 1, 0, 0, 0, 1;
}
if (code == "Golay")
{
dim_u = 12;
dim_mat_col = 24; // also serves as dim of x and y, or simply n
dim_mat_row = 12;
dim_mat_col_H = dim_mat_col;
dim_mat_row_H = dim_mat_col - dim_mat_row;
P = MatrixXi::Zero(dim_u, dim_mat_col - dim_u);
P << 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1,
0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0,
0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1,
1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0,
1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1,
1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0,
0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1,
0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1,
1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1;
}
int N = 1000000; // number of simulations
bool c_hat_minus_c = 0;
int val = 0;
Encode vec(dim_u, dim_mat_row, dim_mat_col);
awgn channel(dim_mat_col);
Decode dec(dim_mat_col, dim_mat_row_H, dim_mat_col_H, P);
vec.encodeDataVector(dim_u, dim_mat_col, P);
// std::cout << "modulated x: " << vec.x << std::endl;
channel.addGausian(vec.x);
// std::cout << channel.y << std::endl;
c_hat_minus_c = dec.decodingalg(6000, channel.y, P, vec.x); // check if codeword is received correctly
// std::cout << channel.y << std::endl;
// std::cout << "val: " << val << std::endl;
}
If I wrap the stack allocated objects in a for loop like this:
for (int i = 0; i < N; i++)
{
Encode vec(dim_u, dim_mat_row, dim_mat_col);
awgn channel(dim_mat_col);
Decode dec(dim_mat_col, dim_mat_row_H, dim_mat_col_H, P);
vec.encodeDataVector(dim_u, dim_mat_col, P);
// std::cout << "modulated x: " << vec.x << std::endl;
channel.addGausian(vec.x);
// std::cout << channel.y << std::endl;
c_hat_minus_c = dec.decodingalg(6000, channel.y, P, vec.x); // check if codeword is received correctly
// std::cout << channel.y << std::endl;
// std::cout << "val: " << val << std::endl;
}
The program breaks and says:
/usr/include/eigen3/Eigen/src/Core/CommaInitializer.h:97: Eigen::CommaInitializer& Eigen::CommaInitializer::operator,(const Eigen::DenseBase&) [with OtherDerived = Eigen::Matrix<int, -1, -1>; XprType = Eigen::Matrix<int, -1, -1>]: Assertion `(m_col + other.cols() <= m_xpr.cols()) && "Too many coefficients passed to comma initializer (operator<<)"' failed.
Edit:
so I basically found out that it braks in encode.cpp
the second time it tries to initialize the Matrix G_
#include <iostream>
#include "encode.h"
#include "awgn.h"
#include <cstdlib> // rand and srand
#include <ctime> // For the time function
using namespace std;
using namespace Eigen;
Encode::Encode(int dim_u, int dim_mat_row, int dim_mat_col) //(7,4) Hamming code only up to now
{
// if (code == "Hamming")
// dim_u = 4;
// dim_mat_col = 7;
// dim_mat_row = 4;
u_ = RowVectorXi::Zero(dim_u);
G_ = MatrixXi::Zero(dim_mat_row, dim_mat_col);
}
void Encode::encodeDataVector(int dim_u, int dim_mat_col, MatrixXi &P)
{
// Get the system time.
unsigned seed = time(0);
// Seed the random number generator.
srand(seed);
for (int i = 0; i < dim_u; i++)
{
u_(i) = rand() % 2; // only zeros and ones
}
// cout << u_ << endl << endl;
MatrixXi I;
// I = MatrixXi::Zero(7, 7);
I = MatrixXi::Identity(dim_u, dim_u);
G_ << I, P; **<----- here**
// cout << G_ << endl << endl;
x = u_ * G_;
for (int i = 0; i < dim_mat_col; i++)
{
x(i) = x(i) % 2;
}
// std::cout << "correct codeword: " << x << std::endl;
// mapping for BPSK
for (int i = 0; i < dim_mat_col; i++)
{
if (x(i) == 0)
x(i) = 1;
else
x(i) = -1;
}
// awgn::awgn channel(dim_mat_col);
// channel.addGausian(this->x);
}
P is being passed by non-const reference, which means it may be modified by the functions you call. Passing a copy of P in each iteration makes sure that the modifications to P stay local to that iteration:
for (int i = 0; i < N; i++) {
MatrixXi P_copy = P;
...
}

GSL complex matrix - eigenvalues/eigenvectors

I've written a program which is computing the eigenvalues and eigenvectors of a hermitian matrix.
Does anyone know how this is done in GSL properly? Here is what I already have.
//hermitian matrix
0 1 0 -i
1 0 -i 0
0 i 0 1
i 0 1 0
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_complex.h>
#include <gsl/gsl_complex_math.h>
#include <gsl/gsl_eigen.h>
using namespace std;
const int N = 4;
int main(){
gsl_eigen_hermv_workspace *workN = gsl_eigen_hermv_alloc(N);
gsl_matrix_complex *A = gsl_matrix_complex_alloc(N, N);
gsl_complex i = gsl_complex_rect(0.0,1.0);
gsl_complex ii = gsl_complex_rect(0.0,-1.0);
gsl_vector *eval = gsl_vector_alloc(N);
gsl_matrix_complex *evec = gsl_matrix_complex_alloc(N, N);
double mTab[] = {
0, 1, 0, 5,
1, 0, 5, 0,
0, 5, 0, 1,
5, 0, 1, 0
};
gsl_matrix_complex_view tmpM = gsl_matrix_complex_view_array(mTab, N, N);
gsl_matrix_complex_memcpy(A, &tmpM.matrix);
gsl_matrix_complex_set(A, 0, 3, ii);
gsl_matrix_complex_set(A, 1, 2, ii);
gsl_matrix_complex_set(A, 2, 1, i);
gsl_matrix_complex_set(A, 3, 0, i);
gsl_eigen_hermv(A, eval, evec, workN);
for(int i=0; i < N; i++){
for(int j=0; j < N; j++){
gsl_complex z = gsl_matrix_complex_get(A, i, j);
cout << GSL_REAL(z) << "+ i" << GSL_IMAG(z) << " ";
}
cout << "\n";
}
cout << "\n";
for(int i=0; i < N; i++){
cout << gsl_vector_get(eval, i) << " ";
}
return 0;
}
This is how I output the eigenvectors
for(int i=0; i < N; i++){
for(int j=0; j < N; j++){
gsl_complex z = gsl_matrix_complex_get(A, i, j);
cout << GSL_REAL(z) << "+ i" << GSL_IMAG(z) << " ";
}
cout << "\n";
}
Finally, here's the way I declared the matrix in question.
double mTab[] = {
0, 1, 0, 5,
1, 0, 5, 0,
0, 5, 0, 1,
5, 0, 1, 0
};
Later, I added the complex numbers.
I managed to print the eigenvectors but I don't know how to do that for the eigenvalues. Any help with that is appreciated?.
You have an error in using the double mTab for gsl_matrix_complex_view_array. This assumes an array of complex numbers represented as real parts followed by imaginary parts in one large array of double values. You can change your definition to:
double mTab[] = {
0, 0, 1, 0, 0, 0, 5, 0,
1, 0, 0, 0, 5, 0, 0, 0,
0, 0, 5, 0, 0, 0, 1, 0,
5, 0, 0, 0, 1, 0, 0, 0,
};
(Which also means you don't need to use a "dummy" variable of 5 just to rewrite it by ±i later.) Then the code for printing eigenvalues works well.
Also you have a typo in the eigenvector printing loop: it should be
gsl_complex z = gsl_matrix_complex_get(evec, i, j);
not
gsl_complex z = gsl_matrix_complex_get(A, i, j);

Getting more than a one pixel value in a single contour

Hello after connected component labeling for a single label why am I getting more than a one pixel value ?
this is my image
#include <iostream>
#include <vector>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
void FindBlobs(const cv::Mat &binary, std::vector < std::vector<cv::Point2i> > &blobs);
int main(int argc, char **argv)
{
cv::Mat img = cv::imread("/Users/Rodrane/Documents/XCODE/test/makalesvm/persembe.png", 0); if(!img.data) {
std::cout << "File not found" << std::endl;
return -1;
}
cv::namedWindow("binary");
cv::namedWindow("labelled");
cv::Mat output = cv::Mat::zeros(img.size(), CV_8UC3);
cv::Mat binary;
std::vector < std::vector<cv::Point2i > > blobs;
equalizeHist( img , img );
cv::threshold(img, binary, 0, 1, cv::THRESH_BINARY_INV);
FindBlobs(binary, blobs);
// Randomy color the blobs
for(size_t i=0; i < blobs.size(); i++) {
unsigned char r = 255 * (rand()/(1.0 + RAND_MAX));
unsigned char g = 255 * (rand()/(1.0 + RAND_MAX));
unsigned char b = 255 * (rand()/(1.0 + RAND_MAX));
for(size_t j=0; j < blobs[i].size(); j++) {
int x = blobs[i][j].x;
int y = blobs[i][j].y;
output.at<cv::Vec3b>(y,x)[0] = b;
output.at<cv::Vec3b>(y,x)[1] = g;
output.at<cv::Vec3b>(y,x)[2] = r;
}
}
cout << "H = "<< endl << " " << output << endl << endl;
cv::imshow("binary", img);
cv::imshow("labelled", output);
cv::waitKey(0);
return 0;
}
void FindBlobs(const cv::Mat &binary, std::vector < std::vector<cv::Point2i> > &blobs)
{
blobs.clear();
// Fill the label_image with the blobs
// 0 - background
// 1 - unlabelled foreground
// 2+ - labelled foreground
cv::Mat label_image;
binary.convertTo(label_image, CV_32SC1);
int label_count = 2; // starts at 2 because 0,1 are used already
for(int y=0; y < label_image.rows; y++) {
int *row = (int*)label_image.ptr(y);
for(int x=0; x < label_image.cols; x++) {
if(row[x] != 1) {
continue;
}
cv::Rect rect;
cv::floodFill(label_image, cv::Point(x,y), label_count, &rect, 0, 0, 4);
std::vector <cv::Point2i> blob;
for(int i=rect.y; i < (rect.y+rect.height); i++) {
int *row2 = (int*)label_image.ptr(i);
for(int j=rect.x; j < (rect.x+rect.width); j++) {
if(row2[j] != label_count) {
continue;
}
blob.push_back(cv::Point2i(j,i));
}
}
blobs.push_back(blob);
label_count++;
}
}
}
actually this is a single label when I print the image
however when I check pixel values. I see there is actually 2 different values (I just write down part of the matrix not all)
H = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 33, 0, 192, 33, 0, 192, 33, 0, 0, 0, 0, ]
also by adding this line of code to the last line of FindBlobs function I recieve 3 since the label_count variable starts from 2 this also proves that H is a single label.
cout << "number of labels = "<< endl << " " << label_count << endl << endl;

InvalidCursor error from multi-threaded SDL application

I rewrote Lode's raycasting tutorial code to make it process events in a separate thread. I found out that any SDL calls that call xlib functions need to be the main thread, so in this code all functions that rely on xlib are in the main thread.
This is the error I still get randomly from the application:
X Error of failed request: BadCursor (invalid Cursor parameter)
Major opcode of failed request: 95 (X_FreeCursor)
Resource id in failed request: 0x4a0000b
Serial number of failed request: 108
Current serial number in output stream: 107
Sometimes when I run it I'll get this error, but if I run it again it will work.
I'm not for sure how else I need to change the code because all of the graphics processing is in the main thread, the separate thread only deals with events processing. Does anybody know what I'm doing wrong?
raycaster.cpp
#include <iostream>
#include <cmath>
#include "SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
#include "game.hpp"
using std::cout;
static int SCREENW = 500;
static int SCREENH = 500;
static int BPP = 32;
int events_loop(void* data);
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD);
TTF_Init();
SDL_Thread* events;
Game_state* gs = new Game_state();
events = SDL_CreateThread(events_loop, (void*)gs);
SDL_Surface* screen = SDL_SetVideoMode(SCREENW, SCREENH, BPP, SDL_SWSURFACE);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
SDL_WM_SetCaption("Raycaster (non-textured)", NULL);
Game* game = new Game(screen, SCREENW, SCREENH, BPP);
//BEGIN GAME VARIABLES
//game map
int map[Game::MAP_WIDTH][Game::MAP_WIDTH] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 4, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 4, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1 },
{ 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
//direction variables
double pos_x = Game::PLAYER_START_X;
double pos_y = Game::PLAYER_START_Y;
double dir_x = -1; double old_dir_x;
double dir_y = 0;
int map_x, map_y;
//timing variables
double start_ticks = 0;
double end_ticks = 0;
double frame_time = 0;
//camera varibales
double camera_x;
double ray_pos_x, ray_pos_y;
double ray_dir_x, ray_dir_y;
double plane_x = 0; double plane_y = Game::FOV; double old_plane_x;
int line_height;
//DDA variables
double side_dist_x, side_dist_y;
double delta_dist_x, delta_dist_y;
double perpen_wall_dist;
int step_x, step_y;
bool EW_side; //east west side hit, negative implies north south side
bool hit = false;
//drawing variables
int draw_low_y, draw_high_y;
int r, g, b;
//movement variables
double move_speed, rotation_speed;
//BEGIN RENDERING LOGIC
while(gs->over == false) {
start_ticks = SDL_GetTicks();
//lock screen to modify its pixels
/*if(SDL_MUSTLOCK(screen)) {
SDL_LockSurface(screen);
}*/
game->clear_screen();
//BEGIN DRAWING PIXELS
for(int x = 0; x < SCREENW; x++) {
//set up camera
camera_x = 2 * x / (double(SCREENW) - 1);
ray_pos_x = pos_x; ray_pos_y = pos_y;
ray_dir_x = dir_x + plane_x * camera_x;
ray_dir_y = dir_y + plane_y * camera_x;
delta_dist_x = sqrt(1 + (ray_dir_y * ray_dir_y) / (ray_dir_x * ray_dir_x));
delta_dist_y = sqrt(1 + (ray_dir_x * ray_dir_x) / (ray_dir_y * ray_dir_y));
//what box are we in?
map_x = int(ray_pos_x); map_y = int(ray_pos_y);
//calculate step and side_dist
if(ray_dir_x < 0) {
step_x = -1;
side_dist_x = (ray_pos_x - map_x) * delta_dist_x;
}
else {
step_x = 1;
side_dist_x = (map_x + 1.0 - ray_pos_x) * delta_dist_x;
}
if(ray_dir_y < 0) {
step_y = -1;
side_dist_y = (ray_pos_y - map_y) * delta_dist_y;
}
else {
step_y = 1;
side_dist_y = (map_y + 1.0 - ray_pos_y) * delta_dist_y;
}
//step using DDA until a wall is hit
hit = false;
while(hit == false) {
if(side_dist_x < side_dist_y) {
side_dist_x += delta_dist_x;
map_x += step_x;
EW_side = false;
}
else {
side_dist_y += delta_dist_y;
map_y += step_y;
EW_side = true;
}
if(map[map_x][map_y] > 0) { hit = true; }
}
//calculate dist from camera to wall that was hit
if(EW_side == false) {
perpen_wall_dist = fabs((map_x - ray_pos_x + (1 - step_x) / 2) / ray_dir_x);
}
else {
perpen_wall_dist = fabs((map_y - ray_pos_y + (1 - step_y) / 2) / ray_dir_y);
}
//calculate line height from perpendicular wall distance
line_height = abs(int(SCREENH / perpen_wall_dist));
//calculate how high to draw the line
draw_high_y = -line_height / 2 + SCREENH / 2;
if(draw_high_y < 0) { draw_high_y = 0; }
draw_low_y = line_height / 2 + SCREENH / 2;
if(draw_low_y >= SCREENH) { draw_low_y = SCREENH - 1; }
if(draw_low_y < 0) { draw_low_y = 0; } //added (shouldn't need to be here)
//finally draw the line
game->draw_line(x, draw_low_y, draw_high_y, map[map_x][map_y], EW_side);
}
//unlock screen for blitting
/*if(SDL_MUSTLOCK(screen)) {
SDL_UnlockSurface(screen);
}*/
//calculate timing and print the FPS
end_ticks = SDL_GetTicks();
frame_time = (end_ticks - start_ticks) / 1000.0;
game->blit_fps(frame_time);
game->blit_location(map_x, map_y);
if(SDL_Flip(screen) != 0) {
cout << "ERROR: couldn't draw to the screen <" << SDL_GetError() << ">\n";
}
//BEGIN CALCULATING NEXT STEP
//calculate new direction based on frames drawn
move_speed = frame_time * Game_state::MOVEMENT_MULTIPLIER;
rotation_speed = frame_time * Game_state::ROTATION_MULTIPLIER;
//process movement for next frame
if(gs->movement_forward == Game_state::MOVE_UP) {
if(map[int(pos_x + dir_x * move_speed)][int(pos_y)] == 0) { pos_x += dir_x * move_speed; }
if(map[int(pos_x)][int(pos_y + dir_y * move_speed)] == 0) { pos_y += dir_y * move_speed; }
}
else if(gs->movement_forward == Game_state::MOVE_DOWN) {
if(map[int(pos_x - dir_x * move_speed)][int(pos_y)] == 0) { pos_x -= dir_x * move_speed; }
if(map[int(pos_x)][int(pos_y - dir_y * move_speed)] == 0) { pos_y -= dir_y * move_speed; }
}
if(gs->movement_side == Game_state::MOVE_RIGHT) {
old_dir_x = dir_x;
dir_x = dir_x * cos(-rotation_speed) - dir_y * sin(-rotation_speed);
dir_y = old_dir_x * sin(-rotation_speed) + dir_y * cos(-rotation_speed);
old_plane_x = plane_x;
plane_x = plane_x * cos(-rotation_speed) - plane_y * sin(-rotation_speed);
plane_y = old_plane_x * sin(-rotation_speed) + plane_y * cos(-rotation_speed);
}
else if(gs->movement_side == Game_state::MOVE_LEFT) {
old_dir_x = dir_x;
dir_x = dir_x * cos(rotation_speed) - dir_y * sin(rotation_speed);
dir_y = old_dir_x * sin(rotation_speed) + dir_y * cos(rotation_speed);
old_plane_x = plane_x;
plane_x = plane_x * cos(rotation_speed) - plane_y * sin(rotation_speed);
plane_y = old_plane_x * sin(rotation_speed) + plane_y * cos(rotation_speed);
}
}
delete gs;
delete game;
return 0;
}
int events_loop(void* data) {
Game_state* gs = (Game_state*)data;
SDL_Event evt;
while(1) {
while(SDL_PollEvent(&evt)) {
if(evt.type == SDL_QUIT) { gs->over = true; cout << "quit\n"; return 0; }
else if(evt.type == SDL_KEYDOWN) {
if(evt.key.keysym.sym == SDLK_w) {
gs->move(Game_state::MOVE_UP);
}
else if(evt.key.keysym.sym == SDLK_s) {
gs->move(Game_state::MOVE_DOWN);
}
else if(evt.key.keysym.sym == SDLK_a) {
gs->move(Game_state::MOVE_LEFT);
}
else if(evt.key.keysym.sym == SDLK_d) {
gs->move(Game_state::MOVE_RIGHT);
}
else if(evt.key.keysym.sym == SDLK_ESCAPE) { gs->over = true; cout << "escape\n"; return 0; }
}
else if(evt.type == SDL_KEYUP) {
if(evt.key.keysym.sym == SDLK_w) {
gs->stop_move(Game_state::MOVE_UP);
}
else if(evt.key.keysym.sym == SDLK_s) {
gs->stop_move(Game_state::MOVE_DOWN);
}
else if(evt.key.keysym.sym == SDLK_a) {
gs->stop_move(Game_state::MOVE_LEFT);
}
else if(evt.key.keysym.sym == SDLK_d) {
gs->stop_move(Game_state::MOVE_LEFT);
}
}
else { /* ignore */ }
}
}
}
game.cpp
#include <iostream>
#include "game.hpp"
using std::cout; using std::endl;
Game_state::Game_state() {
movement_forward = NO_MOVE;
movement_side = NO_MOVE;
over = false;
}
void Game_state::move(int direction) {
switch(direction) {
case NO_MOVE:
break;
case MOVE_UP:
if(movement_forward == MOVE_DOWN) { movement_forward = NO_MOVE; }
else { movement_forward = MOVE_UP; }
break;
case MOVE_DOWN:
if(movement_forward == MOVE_UP) { movement_forward = NO_MOVE; }
else { movement_forward = MOVE_DOWN; }
break;
case MOVE_LEFT:
if(movement_side == MOVE_RIGHT) { movement_side = NO_MOVE; }
else { movement_side = MOVE_LEFT; }
break;
case MOVE_RIGHT:
if(movement_side == MOVE_LEFT) { movement_side = NO_MOVE; }
else { movement_side = MOVE_RIGHT; }
break;
default:
cout << "ERROR: invalid movement in Game_state::move() at time " << SDL_GetTicks() << endl;
break;
}
}
void Game_state::stop_move(int direction) {
switch(direction) {
case NO_MOVE:
break;
case MOVE_UP:
case MOVE_DOWN:
movement_forward = NO_MOVE;
break;
case MOVE_RIGHT:
case MOVE_LEFT:
movement_side = NO_MOVE;
break;
default:
cout << "ERROR: invalid movement in Game_state::stop_move() at time " << SDL_GetTicks() << endl;
break;
}
}
Game::Game(SDL_Surface* scr, int w, int h, int b) {
screen = scr;
scr_w = w; scr_h = h; bpp = b;
//fps printing vars
fps_location.x = 0; fps_location.y = 0;
fps_font = TTF_OpenFont("/usr/share/fonts/truetype/ttf-liberation/LiberationMono-Regular.ttf", 24);
fps_color.r = 0; fps_color.g = 0; fps_color.b = 255; //blue
//location printing vars
location_font = TTF_OpenFont("/usr/share/fonts/truetype/ttf-liberation/LiberationMono-Regular.ttf", 18);
//determine how high the font surface should be from the bottom
location_color.r = 0; location_color.g = 90; location_color.b = 240;
location_surface = TTF_RenderText_Solid(location_font, location_buffer, location_color);
location_location.x = 0; location_location.y = scr_h - location_surface->clip_rect.h;
//set up the wall colors
wall_color[OUTSIDE_WALL].r = 255; wall_color[OUTSIDE_WALL].g = 255; wall_color[OUTSIDE_WALL].b = 255;
wall_color[RED_WALL].r = 255; wall_color[RED_WALL].g = 0; wall_color[RED_WALL].b = 0;
wall_color[GRAY_WALL].r = 160; wall_color[GRAY_WALL].g = 160; wall_color[GRAY_WALL].b = 160;
wall_color[GOLD_WALL].r = 232; wall_color[GOLD_WALL].g = 211; wall_color[GOLD_WALL].g = 34;
}
void Game::clear_screen() {
SDL_FillRect(screen, &screen->clip_rect, SDL_MapRGB(screen->format, 0, 0, 0));
}
void Game::blit_fps(double frame_time) {
sprintf(fps_buffer, "FPS: %3.3f", 1.0 / frame_time);
fps_surface = TTF_RenderText_Solid(fps_font, fps_buffer, fps_color);
if(SDL_BlitSurface(fps_surface, NULL, screen, &fps_location) != 0) {
cout << "ERROR: couldn't blit the FPS surface <" << SDL_GetError() << ">\n";
}
}
void Game::blit_location(int x, int y) {
sprintf(location_buffer, "location: %d, %d", x, y);
location_surface = TTF_RenderText_Solid(location_font, location_buffer, location_color);
if(SDL_BlitSurface(location_surface, NULL, screen, &location_location) != 0) {
cout << "ERROR: couldn't blit the location surface <" << SDL_GetError() << ">\n";
}
}
//high_y means the y coord closest to the top of the screen
void Game::draw_line(int x, int low_y, int high_y, int wall_type, bool EW_side) {
//cout << "high_y = " << high_y << " low_y = " << low_y << endl;
int r = wall_color[wall_type].r;
int g = wall_color[wall_type].g;
int b = wall_color[wall_type].b;
if(EW_side == true) { r /= 2; g /= 2; b /= 2; }
//cout << "r = " << r << " g = " << g << " b = " << b << "\n";
//draw ceiling
/*for(int y = 0; y < high_y - 1; y++) {
put_pixel(x, y, 0, 255, 90);
}*/
for(int y = high_y; y <= low_y; y++) {
put_pixel(x, y, r, g, b);
}
//draw floor (checkered)
/*for(int y = low_y + 1; y <= scr_h; y++) {
if(x % 20 > 10 && y % 20 > 10) {
put_pixel(x, y, 255, 255, 255);
}
}*/
}
void Game::put_pixel(int x, int y, int r, int g, int b) {
int bpp = screen->format->BytesPerPixel;
Uint8* p = (Uint8*)screen->pixels + y * screen->pitch + x * bpp;
Uint32 pixel = SDL_MapRGB(screen->format, r, g, b);
switch(bpp) {
case 1:
*p = pixel;
break;
case 2:
*(Uint16*)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32*)p = pixel;
break;
}
}
game.hpp
#include "SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
class Game_state {
public:
//movement statics
static const int NO_MOVE = 0;
static const int MOVE_UP = 1;
static const int MOVE_DOWN = 2;
static const int MOVE_LEFT = 3;
static const int MOVE_RIGHT = 4;
static const double MOVEMENT_MULTIPLIER = 5.0;
static const double ROTATION_MULTIPLIER = 3.0;
int movement_forward;
int movement_side;
bool over;
Game_state();
void move(int direction);
void stop_move(int direction);
};
class Game {
private:
//fps vars
char fps_buffer[50];
TTF_Font* fps_font;
SDL_Surface* fps_surface;
SDL_Rect fps_location;
SDL_Color fps_color;
//location vars
char location_buffer[24];
TTF_Font* location_font;
SDL_Surface* location_surface;
SDL_Rect location_location;
SDL_Color location_color;
void put_pixel(int x, int y, int r, int g, int b);
public:
//game statics
static const int MAP_WIDTH = 20;
static const int MAP_HEIGHT = 20;
static const double FOV = 0.66;
static const int PLAYER_START_X = 1;
static const int PLAYER_START_Y = 1;
//wall options
static const int FLOOR = 0;
static const int OUTSIDE_WALL = 1;
static const int RED_WALL = 2;
static const int GRAY_WALL = 3;
static const int GOLD_WALL = 4;
//game variables
SDL_Surface* screen;
int scr_w;
int scr_h;
int bpp;
SDL_Color wall_color[5];
Game(SDL_Surface* scr, int w, int h, int b);
void clear_screen();
void blit_fps(double frame_time);
void blit_location(int x, int y);
void draw_line(int x, int low_y, int high_y, int wall_type, bool EW_side);
};
SDL_PollEvent documentation states (clearly for SDL 1.2 at least) that it should only be called from the same thread that set the video mode.