I'm new to Ncurses and I tried to make a program in C++ that makes a window then displays a box and text on both the box and standard screen.
Here is my code
#include <iostream>
#include <ncurses.h>
using namespace std;
int main(){
initscr();
int h,w,y,x;
h = 10;
w = 25;
y = 15;
x = 20;
WINDOW * win = newwin(h ,w, y, x);
box(win,0,0);
wrefresh(win);
printw("Hello");
wprintw(win,"hi");
wrefresh(win);
getch();
refresh();
endwin();
return 0;
}
Any help is greatly appreciated.
It's possible that the problem is with the window's position (y and x coordinates). Set y=0 and x=0 to position the window in the upper-left corner of the screen and see if it appears.
You can also check if ncurses is properly initialised by adding if (!initscr()) endwin(); return 1;} at the beginning of the main function to ensure that ncurses has been successfully initialised.
The updated code is as follows:
#include <iostream>
#include <ncurses.h>
int main() {
if (!initscr()) {
endwin();
return 1;
}
int h = 10, w = 25, y = 0, x = 0;
WINDOW *win = newwin(h, w, y, x);
box(win, 0, 0);
wrefresh(win);
printw("Hello");
wprintw(win, "hi");
wrefresh(win);
getch();
refresh();
endwin();
return 0;
}
Related
I am coding a terminal based game in c++ using the ncurses library, and I would like the enemy class to be able to access the players location which I can access from within my main function using p->yLoc and p->xLoc, however, I cannot access these variables from within my enemy::move function, as it just returns the error p was not declared in this scope.
Here is my code:
enemy.h:
#ifndef _ENEMY_H_
#define _ENEMY_H_
#include "player.h"
#include <unistd.h>
void Enemy::move(){
int playerY, playerX;
int yMv, xMv;
while (1){
playerY = p->yLoc;
playerX = p->xLoc;
if (playerY > yLoc) {
mvdown();
} else if (playerY < yLoc) {
mvup();
}
if (playerX > xLoc){
mvright();
} else if (playerX < xLoc) {
mvleft();
}
sleep(1);
}
}
player.h
#ifndef _PLAYER_H_
#define _PLAYER_H_
class Player {
public:
Player(WINDOW * win, int y, int x, char c);
void mvup();
void mvdown();
void mvleft();
void mvright();
int getmv();
void display();
int xLoc, yLoc, xMax, yMax;
private:
char character;
WINDOW * curwin;
};
Player::Player(WINDOW * win, int y, int x, char c){
curwin = win;
yLoc = y;
xLoc = x;
getmaxyx(curwin, yMax, xMax);
keypad(curwin, true);
character = c;
}
main.cpp
#include <ncurses.h>
#include "player.h"
#include <string>
#include <ctime>
#include <cstdlib>
#include "enemy.h"
#include <thread>
using namespace std; // I understand this is bad practice
int main(){
// starts ncurses
initscr();
noecho();
cbreak();
int yMax, xMax;
getmaxyx(stdscr, yMax, xMax);
WINDOW * playwin = newwin(20, 50, (yMax/2)-10, 10);
box(playwin, 0, 0);
refresh();
wrefresh(playwin);
if (nodelay (playwin, 1) == ERR) {
// an error has occurred
}
Player * p = new Player(playwin, 1, 1, '#'); // params: (window to display in, starting y, starting x, character to display)
Enemy * e = new Enemy(playwin, 10, 10, 'x'); // same here
thread enemyLoop(&Enemy::move, e); // start the movement for the enemy in a different thread
while(p->getmv() != 'x'){ // leave the game with the key x
// updates the location of the two sprites, and refreshes the window.
p->display();
e->display();
wrefresh(playwin);
}
endwin();
return 0;
}
If Enemy::move is supposed to know about the other players location then you have to pass the player as argument:
void Enemy::move(const Player &p)
e->move(*p);
Then the function can access the players position.
Note: why are you allocating the player and enemy on the heap. there really is no need for that.
I'm trying to make a library to simplify the ncurses use to display colors. I'm doing it object-oriented so it'll easy to handle changes in the future. But the problem is that I can't get to work this code.
#include <ncurses.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <iostream>
using namespace std;
class ColorWindow {
private:
bool canColor;
WINDOW* container;
int height, width, startx, starty;
public:
ColorWindow() {
if(has_colors()) {
canColor=true;
}
this->height = 20;
this->width = 84;
this->starty = (LINES - height) / 2; /* Calculating for a center placement */
this->startx = (COLS - width) / 2;
}
bool writeStringWithColor(int x, int y, const char* message) {
if(!canColor) {
writeString(3, 5, "Sorry, your term can't show colors.");
return false;
}
init_pair(1, COLOR_RED, COLOR_BLACK);
writeString(0, 10, "aaaaaaaaa");
wattron(getContainer(), COLOR_PAIR(1));
writeString(x, y, message);
wattroff(getContainer(), COLOR_PAIR(1));
}
void writeString(int x, int y, const char* message) {
mvwprintw(getContainer(), x, y, message);
}
WINDOW* createNewContainer() {
this->container = newwin(height, width, starty, startx);
wrefresh(this->container); /* Show that box */
return getContainer();
}
WINDOW* getContainer() {
return this->container;
}
void refreshContainer() {
refresh();
wrefresh(this->container); /* Show that box */
}
};
int main() {
ColorWindow cw = ColorWindow();
initscr(); /* Start curses mode */
cbreak(); /* Line buffering disabled, Pass on
* everything to me */
keypad(stdscr, TRUE);
start_color();
cw.createNewContainer();
bool success = cw.writeStringWithColor(0, 10, "Hello everyone in color!!");
if(!success)
cw.writeString(0, 10, "Write with color failed :(");
cw.refreshContainer();
sleep(2);
endwin();
return 0;
}
Thanks in Advance.
There are a couple of bugs in your code:
You don't initialize canColor and container, so copying the fields into cw in main has undefined behavior. Fixed by:
ColorWindow() : canColor(false), container(nullptr) {
writeStringWithColor is missing a return statement at the end, also leading to undefined behavior in main. Fixed by:
return true;
at the end of writeStringWithColor.
Your x and y arguments are swapped in the call to mvwprintw in writeString. Fixed by:
mvwprintw(getContainer(), y, x, message);
LINES and COLS are only valid after ncurses is initialized, so your starty and startx values are garbage. Fixed by moving the initialization of cw after the ncurses init code in main:
initscr(); /* Start curses mode */
cbreak(); /* Line buffering disabled, Pass on
* everything to me */
keypad(stdscr, TRUE);
start_color();
ColorWindow cw = ColorWindow();
Full program:
#include <ncurses.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <iostream>
using namespace std;
class ColorWindow {
private:
bool canColor;
WINDOW* container;
int height, width, startx, starty;
public:
ColorWindow() : canColor(false), container(nullptr) {
if(has_colors()) {
canColor=true;
}
this->height = 20;
this->width = 84;
this->starty = (LINES - height) / 2; /* Calculating for a center placement */
this->startx = (COLS - width) / 2;
}
bool writeStringWithColor(int x, int y, const char* message) {
if(!canColor) {
writeString(3, 5, "Sorry, your term can't show colors.");
return false;
}
init_pair(1, COLOR_RED, COLOR_BLACK);
writeString(0, 10, "aaaaaaaaa");
wattron(getContainer(), COLOR_PAIR(1));
writeString(x, y, message);
wattroff(getContainer(), COLOR_PAIR(1));
return true;
}
void writeString(int x, int y, const char* message) {
mvwprintw(getContainer(), y, x, message);
}
WINDOW* createNewContainer() {
this->container = newwin(height, width, starty, startx);
wrefresh(this->container); /* Show that box */
return getContainer();
}
WINDOW* getContainer() {
return this->container;
}
void refreshContainer() {
refresh();
wrefresh(this->container); /* Show that box */
}
};
int main() {
initscr(); /* Start curses mode */
cbreak(); /* Line buffering disabled, Pass on
* everything to me */
keypad(stdscr, TRUE);
start_color();
ColorWindow cw = ColorWindow();
cw.createNewContainer();
bool success = cw.writeStringWithColor(0, 10, "Hello everyone in color!!");
if(!success)
cw.writeString(0, 10, "Write with color failed :(");
cw.refreshContainer();
sleep(2);
endwin();
return 0;
}
Here is my code which blinks 'Welcome' after user enter his name.
'Welcome' does not blink when user is writing his name. As user hits enter then caret goes into the while loop. Then caret position is set back to the coordinates of 'Welcome' & cout prints 'Welcome' with 5 colors again & again so it seems that 'Welcome' is blinking.
But I want that 'Welcome' blinks continuously as the program starts.
So more likely this question also ask - can we have two caret/cursor at the same time ?
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
int main(int argc, char** argv)
{
int x,y,i;char name[10];
textcolor(10);
x=wherex();y=wherey(); //corrdinates of caret will be stored in x & y.
cout<<"\t\t\t\tWelcome\n";
textcolor(15);
cout<<"\nEnter your name\n";
gets(name);
while(1)
{
for(i=10;i<15;i++)
{
textcolor(i);
gotoxy(x,y); //Transferring caret to the coordinates stored in x & y.
cout<<"\t\t\t\tWelcome";
Sleep(300);
}
}
return 0;
}
I wrote a small code for this question , it's not 100% correct answer. I am just posting this answer just for giving little bit idea to newbie.
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
int x,y,b,l,n=0;
char c;
void blink()
{
{
int m;
for(m=10;m<15;m++)
{
textcolor(m);
gotoxy(x,y);
cout<<"\t\t\t\tWelcome";
Sleep(60);
}
}
}
int main(int argc, char** argv)
{
char i;int key_stroke;
textcolor(10);
x=wherex();y=wherey();
cout<<"\t\t\t\tWelcome\n";
textcolor(15);
cout<<"\nEnter your name\n";
l=wherex();b=wherey();
z:
{
while (1)
{
if(!(_kbhit()))
{
blink();
goto z;
}
else
{
i=_getch();
if(i==13)
{
gotoxy(l+n,b+1);
return 0;
}
textcolor(10);
gotoxy(l+n,b);
cout<<i;n=n+1;
}
}
}
return 0;
}
No we cant have two caret/cursor at the same time. User inputs name first.
It begins to blink right after the user has pressed the enter key
by first displaying the text in a given color and time delay.
Then after it sets the color to black and overwrites the text wth black color.
Windows code:
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
void gotoxy(int x, int y);
void setcolor(WORD color);
void clrscr();
int main(int argc, char** argv){
int x,y,i;char name[10];
setcolor(10);
cout<<"Welcome\n";
setcolor(15);
cout<<"\nEnter your name ";
gets(name);
i=0;
x=22;
y=12;
while(1) {
// counter for text color
i++; if (i>15) i=1;
// print colored text
setcolor(i);
gotoxy(x,y);
cout<<"Welcome "<<name;
Sleep(100);
// Print black text to simulate blink
setcolor(0);
gotoxy(x,y);
cout<<" ";
Sleep(100);
}
setcolor(7);
gotoxy(1,24);
return 0;
}
void setcolor(WORD color)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color);
return;
}
void gotoxy(int x, int y)
{
COORD coord;
coord.X = x; coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
return;
}
void clrscr()
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
return;
}
Instead of such Codes you can use BLINK in textcolor() function. the only problem is that you cannot control its speed. thats it. otherwise its easy to use and you can also set text color.
Eg.
textcolor ( RED + BLINK ) ;
cprintf ( " /t/t WELCOME " ) ;
thats it. I didn't had time to read your full question and program. Also I am just a newbie. So I hope this helps you and others.
So, after following the advise from the stackexchange users about mouse event, I was able to understand and implement some simple task using mouse clicks. So, the next goal was to draw a simple line using the mouse left click and mouse right click. Unfortunately, I can't see any line after I implemented my program.
int x,y;
Point p(0,0);
Point q(0,0);
Mat xal;
void drawimage()
{
a = q.x - p.x; //i am just checking out the values of a and b to see if the drawimagefunction is being called in the rightmouse click event
b = q.y - p.y;
cout<<" a is :"<<a<<endl;
cout<<"b is:"<<b<<endl;
line(xal,Point(p.x,p.y),Point(q.x,q.y),Scalar(0,0,255),2,8);
}
void onMouse( int event, int x, int y, int f, void* )
{
switch (event)
{
case EVENT_LBUTTONDOWN:
cout<<"Left button was pressed"<<x<<" "<<y<<" "<<endl;
{
p.x = x;
p.y = y;
cout<<"p is:"<<p.x<<p.y<<endl;
}
break;
case EVENT_RBUTTONDOWN:
cout<<"Right button was pressed at :"<<x <<" "<<y<<endl;
{
q.x = x;
q.y = y;
drawimage();//no line is being drawn though i can see that i get the values of a and b in the drawimage function.
}
break;
default:
break;
}
}
int main()
{
xal = imread("pic.JPG);
namedWindow("Picture",1);
setMouseCallback("Picture",onMouse,NULL);
imshow("Picture",xal);
cvwaitkey(0);
}
Add the following after your "line(..)" call in your drawLine() function:
imshow("Picture", xal);
The problem is that you are writing the line to the xal matrix, but you have not updated the image on the screen, which is what the imshow(..) call will do.
Try this one code. It is useful for you.
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
void drawimage()
{
line(xal,Point(p->x,p->y),Point(q->x,q->y),Scalar(0,0,255),2,8);
}
void CallBackFunc(int event, int x, int y, int flags, void *ptr )
{
if ( event == EVENT_LBUTTONDOWN )
{
Point*p = (Point*)ptr;
p->x = x;
p->y = y;
drawimage();
}
else if ( event == EVENT_RBUTTONDOWN )
{
Point*q = (Point*)ptr;
q->x = x;
q->y = y;
drawimage();
}
}
int main(int argc, char** argv)
{
// Read image from file
Point p;
Point q;
Mat xal = imread("MyPic.JPG");
//if fail to read the image
if ( xal.empty() )
{
cout << "Error loading the image" << endl;
return -1;
}
//Create a window
namedWindow("My Window", 1);
//set the callback function for any mouse event
setMouseCallback("My Window", CallBackFunc,&p);
setMouseCallback("My Window", CallBackFunc,&q);
//show the image
imshow("My Window", xal);
// Wait until user press some key
waitKey(0);
return 0;
}
I want to get the position of the current window (its a console window). By current I mean the window I'm programming in, for example if the console is in the top left of the screen I should get X = 0, Y = 0. (By the position of the window I mean the top left of the window respective of the monitor)
#include <windows.h>
#include <iostream>
using namespace std;
int main(){
int X, Y;
GetCurrentWindowPos(&X, &Y); /* How do I do this? */
return 0;
}
void GetWindowPos( int *x, int *y ) {
RECT rect = { NULL };
if( GetWindowRect( GetConsoleWindow(), &rect ) ) {
*x = rect.left;
*y = rect.top;
}
}
Cheers