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.
Related
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!";
}
Hey when I am using this code it seems to place my SBOUND in the same spot and not everywhere on the 2 spot that I want it. I have no idea that the problem is and am mostly new to SFML and cant quite understand what is happening. The main code is like this.
`
#include "MainH.h"
int main()
{
int x = 200;
int y = 200;
sf::RenderWindow window(sf::VideoMode(512, 256), "Tilemap");
// create a new vertex
sf::Vertex vertex;
// set its position
vertex.position = sf::Vector2f(10, 50);
// set its color
vertex.color = sf::Color::Red;
// set its texture coordinates
vertex.texCoords = sf::Vector2f(100, 100);
////////////////////////
sf::Sprite A;
sf::Texture AT;
AT.loadFromFile("Red.png");
A.setTexture(AT);
A.setPosition(16.f, 16.f);
sf::Text A_Tex;
sf::Font A_Font;
A_Font.loadFromFile("arial.ttf");
A_Tex.setFont(A_Font);
A_Tex.setColor(sf::Color::Yellow);
A_Tex.setScale(0.35f,0.35f);
/////////////////////////////
sf::Sprite B;
sf::Texture BT;
BT.loadFromFile("Green.png");
B.setTexture(BT);
B.setPosition(30.f, 30.f);
sf::Text B_Tex;
sf::Font B_Font;
B_Font.loadFromFile("arial.ttf");
B_Tex.setFont(A_Font);
B_Tex.setColor(sf::Color::Yellow);
B_Tex.setScale(0.35f, 0.35f);
const int level[] =
{
5, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
2, 1, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3,
2, 1, 0, 0, 2, 0, 3, 3, 3, 0, 1, 1, 1, 0, 0, 0,
2, 1, 1, 0, 3, 3, 3, 0, 0, 0, 1, 1, 1, 2, 0, 0,
2, 0, 1, 0, 3, 0, 2, 2, 0, 0, 1, 1, 1, 1, 2, 0,
2, 0, 1, 0, 3, 0, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1,
2, 0, 1, 0, 3, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1,
};
sf::Texture COL;
COL.loadFromFile("COL.png");
TileMap map;
if (!map.load("Set.png", sf::Vector2u(16, 16), level, 16, 8, COL))
return -1;
bool Debug = false;
//////////////////////////////
BorderLine C;
sf::Texture BordS;
sf::Texture BordT;
BordS.loadFromFile("Border.png");
BordT.loadFromFile("TopBD.png");
C.Setup(BordS, 16 ,BordT);
////////////////////////////////
window.setKeyRepeatEnabled(false);
while (window.isOpen())
{
C.Object = A.getPosition();
sf::Vector2f APos = A.getPosition();
sf::Vector2f BPos = B.getPosition();
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
if (event.type == sf::Event::Resized)
{
window.setView(sf::View(sf::FloatRect(0, 0, event.size.width, event.size.height)));
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left) && !Collision::PixelPerfectTest(C.A_B_L, B, 256))
{
// left key is pressed: move our character
A.move(-.01f, 0);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && !Collision::PixelPerfectTest(C.A_B_R, B, 256))
{
// left key is pressed: move our character
for (unsigned int i = 0; i < map.SBOUND.size(); ++i)
map.SBOUND[i].move(.01f, 0);
for (unsigned int i = 0; i < map.TEX.size(); ++i)
map.TEX[i].move(.01f, 0);
A.move(.01f, 0);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && !Collision::PixelPerfectTest(C.A_B_T, B, 256))
{
// left key is pressed: move our character
for (unsigned int i = 0; i < map.SBOUND.size(); ++i)
map.SBOUND[i].move(0, -.01f);
for (unsigned int i = 0; i < map.TEX.size(); ++i)
map.TEX[i].move(0, -.01f);
A.move(0, -.01f);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) && !Collision::PixelPerfectTest(C.A_B_B, B, 256))
{
for (unsigned int i = 0; i < map.SBOUND.size(); ++i)
map.SBOUND[i].move(0, .01f);
for (unsigned int i = 0; i < map.TEX.size(); ++i)
map.TEX[i].move(0, .01f);
// left key is pressed: move our character
A.move(0, .01f);
}
A_Tex.setPosition(APos.x + 16, APos.y + 16);
A_Tex.setString(to_string(APos.x) + "," + to_string(APos.y));
B_Tex.setPosition(BPos.x + 16, BPos.y + 16);
B_Tex.setString(to_string(BPos.x) + "," + to_string(BPos.y));
// LEFT window.draw(C.A_B_L);
// RIGHT window.draw(C.A_B_R);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
// left key is pressed: move our character
Debug = true;
}
else
{
Debug = false;
}
window.clear();
window.draw(map);
window.draw(A);
window.draw(B);
C.A();
window.draw(C.A_B_R);
window.draw(C.A_B_L);
window.draw(C.A_B_T);
window.draw(C.A_B_B);
if (Debug) {
window.draw(A_Tex);
window.draw(B_Tex);
}
for (unsigned int i = 0; i < map.SBOUND.size(); ++i)
window.draw(map.SBOUND[i]);
for (unsigned int i = 0; i < map.TEX.size(); ++i)
window.draw(map.TEX[i]);
window.display();
}
return 0;
}`
The class code is as fallowed:
#include "MainH.h"
class TileMap : public sf::Drawable, public sf::Transformable
{
public:
sf::Texture A;
std::vector<sf::Sprite> SBOUND;
std::vector<sf::Text> TEX;
sf::Font FT;
bool load(const std::string& tileset, sf::Vector2u tileSize, const int* tiles, unsigned int width, unsigned int height , sf::Texture& texture)
{
FT.loadFromFile("arial.ttf");
A = texture;
SBOUND.resize(90);
for (int a = 0; a < 88; a = a + 1) {
SBOUND[a].setTexture(A);
}
TEX.resize(90);
for (int a = 0; a < 88; a = a + 1) {
TEX[a].setFont(FT);
TEX[a].setString("HERE");
TEX[a].setColor(sf::Color::Red);
TEX[a].setScale(0.5f,0.5f);
}
// load the tileset texture
if (!m_tileset.loadFromFile(tileset))
return false;
// resize the vertex array to fit the level size
m_vertices.setPrimitiveType(sf::Quads);
m_vertices.resize(width * height * 4);
// populate the vertex array, with one quad per tile
for (unsigned int i = 0; i < width; ++i)
for (unsigned int j = 0; j < height; ++j)
{
// get the current tile number
int tileNumber = tiles[i + j * width];
// find its position in the tileset texture
int tu = tileNumber % (m_tileset.getSize().x / tileSize.x);
int tv = tileNumber / (m_tileset.getSize().x / tileSize.x);
// get a pointer to the current tile's quad
sf::Vertex* quad = &m_vertices[(i + j * width) * 4];
// define its 4 corners
quad[0].position = sf::Vector2f(i * tileSize.x, j * tileSize.y);
quad[1].position = sf::Vector2f((i + 1) * tileSize.x, j * tileSize.y);
quad[2].position = sf::Vector2f((i + 1) * tileSize.x, (j + 1) * tileSize.y);
quad[3].position = sf::Vector2f(i * tileSize.x, (j + 1) * tileSize.y);
if (tileNumber == 2) {
std::cout << tileNumber << std::endl;
SBOUND[j].setPosition(sf::Vector2f((i + 1) * tileSize.x, (j + 1) * tileSize.y));
TEX[j].setPosition(sf::Vector2f(i * tileSize.x, j * tileSize.y));
sf::Vector2f V;
V = SBOUND[j].getPosition();
std::cout << V.x << " , " << V.y << std::endl;
std::cout << tileSize.x * i << " Tile_X " << std::endl;
std::cout << tileSize.y * (j+1) << " Tile_Y " << std::endl;
}
// define its 4 texture coordinates
quad[0].texCoords = sf::Vector2f(tu * tileSize.x, tv * tileSize.y);
quad[1].texCoords = sf::Vector2f((tu + 1) * tileSize.x, tv * tileSize.y);
quad[2].texCoords = sf::Vector2f((tu + 1) * tileSize.x, (tv + 1) * tileSize.y);
quad[3].texCoords = sf::Vector2f(tu * tileSize.x, (tv + 1) * tileSize.y);
}
return true;
}
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
// apply the transform
states.transform *= getTransform();
// apply the tileset texture
states.texture = &m_tileset;
// draw the vertex array
target.draw(m_vertices, states);
}
sf::VertexArray m_vertices;
sf::Texture m_tileset;
};
The tile index should be on top of every tile that is Id 2. It only covers some and not all of them.
Solved: I was just getting the wrong Points for the sprites
This is an SFML project that I have been working on. I created a mouse and positioned it at a specific location. When I try to update its position using the Keyboard events, it moves but goes back to its original position after a short while. Also when I try to move the mouse right or down, it simply disappears then also reappears a while later. There are also seems to be the problem of me not able to go anywhere beyond 1 tile in the four directions.
Any Help would be appreciated.
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace std;
int main()
{
sf::Vector2f screenDimensions(800, 800);
sf::RenderWindow Window;
Window.create(sf::VideoMode(screenDimensions.x, screenDimensions.y), "Tile Maps Demo");
int TILE_SIZE = 64; // Size of the tile for both width and height
const int MAP_WIDTH = 10; // Elements in columns
const int MAP_HEIGHT = 10; // Elements in rows
int counter = 0; // Counts which element its on in each row
int map[MAP_HEIGHT][MAP_WIDTH] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 3, 1, 1, 1, 1, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
{ 0, 1, 1, 1, 4, 1, 1, 1, 2, 2 },
{ 0, 1, 1, 1, 1, 1, 1, 1, 2, 2 },
{ 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
{ 0, 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, 0, 0, 0, 0 } };
sf::Sprite water;
sf::Sprite land;
sf::Sprite bridge;
sf::Sprite cat;
sf::Sprite mouse;
sf::Texture wTexture;
sf::Texture lTexture;
sf::Texture bTexture;
sf::Texture cTexture;
sf::Texture mTexture;
if (!wTexture.loadFromFile("tex_Water2.jpg"))
cout << "Error! image 1 didn't load" << endl;
if (!lTexture.loadFromFile("Sand4.jpg"))
cout << "Error! image 2 didn't load" << endl;
if (!bTexture.loadFromFile("Wood2.jpg"))
cout << "Error! image 3 didn't load" << endl;
if (!cTexture.loadFromFile("TomSand2.jpg"))
cout << "Error! Image 4 didn't load" << endl;
if (!mTexture.loadFromFile("JerrySand3.jpg"))
cout << "Error! Image 5 didn't load" << endl;
water.setTexture(wTexture);
land.setTexture(lTexture);
bridge.setTexture(bTexture);
cat.setTexture(cTexture);
mouse.setTexture(mTexture);
mouse.setPosition(256,256);
while (Window.isOpen())
{
sf::Event Event;
while (Window.pollEvent(Event))
{
switch (Event.type)
{
case sf::Event::Closed:
Window.close();
break;
case sf::Event::KeyPressed:
if (Event.key.code == sf::Keyboard::Escape)
Window.close();
break;
}
}
Window.clear();
// Index on the first row
for (int i = 0; i < MAP_HEIGHT; i++)
{
// Index the first column
for (int j = 0; j < MAP_WIDTH; j++)
{
// count each element
counter++;
if (counter >= MAP_WIDTH)
{
//resets itself to zero when end of a row is reached
counter = 0;
}
if (map[i][j] == 4)
{
// Else if the number is 4, then place this image at that position then draw
//mouse.setPosition(j * TILE_SIZE, i * TILE_SIZE);
{
if (Event.type)
{
int m = i;
int n = j;
if ((Event.type == sf::Event::KeyReleased && Event.key.code == sf::Keyboard::A))
{
// Move left
mouse.setPosition((n-1) * TILE_SIZE, m * TILE_SIZE);
//mouse.move(sf::Vector2f(-64,0));
//Window.draw(mouse);
//land.move(sf::Vector2f(64, 0));
land.setPosition(n * TILE_SIZE, m * TILE_SIZE);
//Window.draw(land);
}
else if ((Event.type == sf::Event::KeyReleased && Event.key.code == sf::Keyboard::D))
{
// Move right
mouse.setPosition((n + 1) * TILE_SIZE, m * TILE_SIZE);
Window.draw(mouse);
land.setPosition(n * TILE_SIZE, m * TILE_SIZE);
Window.draw(land);
//mouse.move(sf::Vector2f(64, 0));
}
else if ((Event.type == sf::Event::KeyReleased && Event.key.code == sf::Keyboard::W))
{
// Move up
mouse.setPosition(n * TILE_SIZE, (m-1) * TILE_SIZE);
Window.draw(mouse);
land.setPosition(n * TILE_SIZE, m * TILE_SIZE);
Window.draw(land);
//mouse.move(sf::Vector2f(0, -64));
}
else if ((Event.type == sf::Event::KeyReleased && Event.key.code == sf::Keyboard::S))
{
// Move down
mouse.setPosition(n * TILE_SIZE, (m+1) * TILE_SIZE);
Window.draw(mouse);
land.setPosition(n * TILE_SIZE, m * TILE_SIZE);
Window.draw(land);
//mouse.move(sf::Vector2f(0,64));
}
}
}
Window.draw(mouse);
}
else if (map[i][j] == 0)
{
// If the number is 0, then place the image at this position then draw
water.setPosition(j * TILE_SIZE, i * TILE_SIZE);
Window.draw(water);
}
else if (map[i][j] == 1)
{
// Else if the number is 1, then place this image at that position then draw
land.setPosition(j * TILE_SIZE, i * TILE_SIZE);
Window.draw(land);
}
else if (map[i][j] == 2)
{
// Else if the number is 2, then place this image at that position then draw
bridge.setPosition(j * TILE_SIZE, i * TILE_SIZE);
Window.draw(bridge);
}
else if (map[i][j] == 3)
{
// Else if the number is 3, then place this image at that position then draw
cat.setPosition(j * TILE_SIZE, i * TILE_SIZE);
Window.draw(cat);
}
}
}
Window.display();
}
return 0;
}
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
I need to write recursive function in c++ that finds largest area of number '1' in 2d array that contains only 1 or 0.
Example:
int Arr[5][8] =
{
{ 0, 0, 0, 0, 1, 1, 0, 0, },
{ 1, 0, 0, 1, 1, 1, 0, 0, },
{ 1, 1, 0, 1, 0, 1, 1, 0, },
{ 0, 0, 0, 1, 1, 1, 1, 0, },
{ 0, 1, 1, 0, 0, 0, 0, 0, },
};
Visual example: http://s23.postimg.org/yabwp6h23/find_largest.png
Largest area of this array is 12, second largest is 3 and third largest is 2.
I was thinking to do this with something similar to flood fill algorithm, but just can't figure out how.
bool visited[5][8];
int i,j;
// variables for the area:
int current_area = 0, max_area = 0;
int Arr[5][8]={ // type your map of values here
}
// functions
void prepare_visited_map() {
for(i=0;i<5;i++) {
for(j=0;j<8;j++) visited[i][j] = false;
}
}
// recursive function to calculate the area around (x,y)
void calculate_largest_area(int x, int y) {
if(visited[x][y]) return;
// check if out of boundaries
if(x<0 || y<0 || x>=5 || y>=8) return;
// check if the cell is 0
if(!Arr[x][y]) {
visited[x][y] = true;
return;
}
// found a propper cell, proceed
current_area++;
visited[x][y] = true;
// call recursive function for the adjacent cells (north, east, south, west)
calculate_largest_area(x,y-1);
calculate_largest_area(x+1,y);
calculate_largest_area(x,y+1);
calculate_largest_area(x-1,y);
// by the end of the recursion current_area will hold the area around the initial cell
}
// main procedure where the above functions are used
int mian() {
// calculate the sorrounding area of each cell, and pick up the largest of all results
for(i=0;i<5;i++) {
for(j=0;j<8;j++) {
prepare_visited_map();
calculate_largest_area(i,j);
if(current_area > max_area) max_area = current_area;
}
}
printf("Max area is %d",max_area");
}
Hope this was helpful :)
I was thinking to do this with something similar to flood fill algorithm
I think that's a pretty good way to do it. Apply flood fill to any 1, counting the ones and replacing them with zeros.
Repeat until the grid consists entirely of zeroes.
The following will print out the sizes of the connected components in no particular order:
#include <iostream>
constexpr int N = 5;
constexpr int M = 8;
int arr[N][M] =
{
{ 0, 0, 0, 0, 1, 1, 0, 0, },
{ 1, 0, 0, 1, 1, 1, 0, 0, },
{ 1, 1, 0, 1, 0, 1, 1, 0, },
{ 0, 0, 0, 1, 1, 1, 1, 0, },
{ 0, 1, 1, 0, 0, 0, 0, 0, },
};
int fill(int arr[N][M], int r, int c) {
int count = 0;
if (r < N && arr[r][c]) {
for (int i = c; i >= 0 && arr[r][i]; --i) {
arr[r][i] = 0;
count += fill(arr, r + 1, i) + 1;
}
for (int i = c + 1; i < M && arr[r][i]; ++i) {
arr[r][i] = 0;
count += fill(arr, r + 1, i) + 1;
}
}
return count;
}
int print_components(int arr[N][M]) {
for (int r = 0; r < N; ++r) {
for (int c = 0; c < M; ++c) {
if (arr[r][c]) {
std::cout << fill(arr, r, c) << std::endl;
}
}
}
}
int main() {
print_components(arr);
}
something like,
int max_area = 0;
foreach y
foreach x
if (pos[y][x] == 1 && !visited[y][x])
{
int area = 0;
Queue queue = new Queue();
queue.push(new Point(x, y));
visited[y][x] = true;
while (!queue.empty())
{
Point pt = queue.pop();
area++;
foreach neightboor of pt (pt.x±1, pt.y±1)
if (pos[neightboor.y][neightboor.x] == 1 && !visited[neightboor.y][neightboor.x])
{
visited[neightboor.y][neightboor.x] = true;
queue.push(new Point(neightboor.x, neightboor.y));
}
}
if (area > max_area)
max_area = area;
}
Quick approach, but I don't know if there is a way to do this in a sane way (recursive
call for each element does not scale for C++ because call stack is limited)
int maxy = 5
int maxx = 8
int areasize(int x, int y) {
if (x < 0 || y < 0 || x > maxx || y > maxy || !Arr[y][x])
return 0;
Arr[y][x] = 0;
return 1
+ areasize(x + 1, y)
+ areasize(x - 1, y)
+ areasize(x, y + 1)
+ areasize(x, y - 1);
}
maxarea = 0;
for (int y = 0; y < maxy; y++) {
for (int x = 0; x < maxx; x++) {
maxarea = std::max(maxarea, areasize(x, y));
}
}