I am working on a C++ game. I was trying to include character input using the getch() method. I need the character code (usually octal code) for Ctrl + ◀ and Ctrl + ▶ to move my objects in the game.
Just like we have a code for Ctrl + Z that is 032.
Here is part of the code I'm using.
if (kbhit())
{
gotoxy(x, y);
cout << h;
i = getch();
if (i == '***') //I need some code here to move my object
{
x=x-5;
}
if (i == '***') //also need here to move it to right ward
{
x=x+5;
}
if (i == LEFT && x>LEFTLIMIT)
{
x = x - 3;
}
else if (i == RIGHT && x<RIGHTLIMIT-6)
{
x = x + 3;
}
}
Using modifier keys I'd suggest using GetAsyncKeyState : MSDN
This way you can check for every key pressed currently or since last call of GetAsyncKeyState
if(GetAsyncKeyState(VK_LEFT) && GetAsyncKeyState(VK_CONTROL)) {
....
}
Related
I am encountering issues with both std::thread and std::mutex, unable to get both to play nicely with each other. I've been pulling my hair out over this for the past few hours and just cannot make any progress whatsoever. I believe it is out of my skill area. The code is just below:
void GekkoFyre::TuiHangouts::gui_userRosterListNav(std::shared_ptr<WINDOW> display,
std::vector<const char *> userList,
const short &menuItem)
{
while (rosterEnabled) {
for (short i = 0; i < totalMenuItems; ++i) {
short diff = (menuItem - i);
if (i < numMenuItems) {
if (i == menuItem) {
size_t msgLen = strlen(userList.at(i));
size_t l = 0;
if (msgLen > subMaxX) {
for (l = subMaxX; l < msgLen; ++l) {
// Scroll the message from left to right, then vice versa, so that it fits within
// the designated window.
std::this_thread::sleep_for(std::chrono::milliseconds(500));
rosterListMutex.lock();
wattron(usrSubWin.get(), A_REVERSE); // Highlight selection
const char *msg = userList.at(i);
mvwaddstr(usrSubWin.get(), i, 0, &msg[(msgLen - l)]);
wrefresh(usrSubWin.get());
touchwin(usrSubWin.get());
rosterListMutex.unlock();
}
} else {
rosterListMutex.lock();
wattron(usrSubWin.get(), A_REVERSE); // Highlight selection
mvwaddstr(usrSubWin.get(), i, 0, userList.at(i));
wrefresh(usrSubWin.get());
touchwin(usrSubWin.get());
rosterListMutex.unlock();
}
}
wattroff(usrSubWin.get(), A_REVERSE); // Remove highlight
if ((i + 1) < numMenuItems) {
mvwaddstr(usrSubWin.get(), (i + 1), 0, userList.at((i + 1)));
}
} else if (diff < (totalMenuItems - numMenuItems) && diff > 0) {
// Allow the scrolling of a username list, from downwards and then back upwards, so that
// the user may see the list in its entirety.
wclear(usrSubWin.get());
int pos = 0;
for (short c = diff; c < (numMenuItems + diff); ++c) {
++pos;
mvwaddstr(usrSubWin.get(), pos, 0, userList.at(c));
}
pos = 0;
break;
}
}
rosterListMutex.lock();
wattroff(usrSubWin.get(), A_REVERSE); // Remove highlight
touchwin(usrSubWin.get());
wrefresh(usrSubWin.get());
wrefresh(display.get());
rosterListMutex.unlock();
}
}
I am trying to display a list of users to the left of a chat window in NCurses, as can be seen in [ 1 ] below, albeit without any users present in said screenshot. I want to keep my privacy :) What happens is that as you scroll down the list, flickering begins to occur back and forth between two usernames after scrolling past just a few. They keep repeatedly selecting each other, just over and over. I believe this is reason of the threads not syncing up properly. The function is implemented as so:
[ 1 ] - http://imgur.com/ZZlFHg2
#define WIDGET_USERS_LIST 1
short menuItem = 0;
int ch = 0;
int curr_widget = 0;
std::thread rosterListNav1(&GekkoFyre::TuiHangouts::gui_userRosterListNav, this, userListWin, rosterFormatted, menuItem);
rosterListNav1.detach();
while ((ch = wgetch(display.get())) != KEY_F(12)) {
switch (ch) {
case KEY_DOWN:
if (curr_widget == WIDGET_USERS_LIST && rosterEnabled) {
++menuItem;
if (menuItem > totalMenuItems - 1) {
menuItem = 0;
}
}
break;
case KEY_UP:
if (curr_widget == WIDGET_USERS_LIST && rosterEnabled) {
--menuItem;
if (menuItem < 0) {
menuItem = totalMenuItems - 1;
}
}
}
std::thread rosterListNav2(&GekkoFyre::TuiHangouts::gui_userRosterListNav, this, userListWin, rosterFormatted, menuItem);
rosterListNav2.detach();
}
Any help on this issue would be dearly appreciated, and I believe I have placed the std::mutex's in the right areas. I am really stumped with this problem. Also beware that while I know a few tricks of the trade, I am entirely self-taught. Some of the nomenclature that is normal to programmers who have gone through university is completely unintelligible to me.
I had recently started working on a chess engine in c++ for an university project but i have a problem in my pawn movement function. I know that the pawn is supposed to move one square forward or attack one square in diagonal. Well my function allows the pawn to attack blank spaces and i do not know why. My board is divided in 2 pieces: one that remembers which player a piece belongs to and one that has the name of the piece (like q,Q,p,P... and blank spaces). A hint would be more than welcome. (sorry for my poor English skills)
The code looks like this:
bool move_P(int move_start_i, int move_start_j, int move_finish_i, int move_finish_j, char table[][9])
{
switch (table[move_finish_i][move_finish_j])
{
case ' ':
{
if (move_start_i - 1 == move_finish_i) // move pawn
{
return true;
}
}
default:
{
if (move_finish_i == move_start_i - 1 && move_finish_j == move_start_j - 1) // atack pawn ^<-
{
if (player[move_finish_i][move_finish_j] == player[move_start_i - 1][move_start_j - 1])
{
return false;
}
else
{
return true;
}
}
else if (move_finish_i == move_start_i - 1 && move_finish_j == move_start_j + 1) // atack pawn ->^
{
if (player[move_finish_i][move_finish_j] == player[move_start_i - 1][move_start_j + 1])
{
return false;
}
else
{
return true;
}
}
}
}
return false;
}
Your player check is wrong,
player[move_finish_i][move_finish_j] == player[move_start_i - 1][move_start_j - 1]
has to be
player[move_finish_i][move_finish_j] == player[move_start_i][move_start_j]
also you should use
return player[move_finish_i][move_finish_j] != player[move_start_i][move_start_j];
The main problem is the check for
move_start_i - 1 == move_finish_i
you have to add a check for the j position!
Insert a
break;
statement at the end of the case ' ': block. Otherwise the default block is executed too if table[move_finish_i][move_finish_j]==' ', which explains why the pawn can move diagonally to blank squares.
Also, the curly brackets after the case and default are not needed. Think of case and default statements as jump labels, code is executed beginning at the first matching case until you leave the switch() {...} block with a break statement (regardless of further 'jump labels').
How can I call an if statement (or any other function) without calling it again, until it's finished executing? I have an update function that calls another function (in another class) but because it executes every update, the user doesn't get the time to actually complete the IF statements (the if statements rely on user input) so therefor it returns nothing or only the first part.
Code (where the update is):
public void Update(){
if(Mouse.isButtonDown(0)){
changeTile();
}
while(Keyboard.next()){
if(Keyboard.getEventKey() == Keyboard.KEY_RIGHT && Keyboard.getEventKeyState()){
moveIndex();
}
if(Keyboard.getEventKey() == Keyboard.KEY_LEFT && Keyboard.getEventKeyState()){
moveIndexBack();
}
}
}
changeTile function:
public void changeTile(){
boolean start = true;
if(start){
while(Mouse.next()){
if(Mouse.getEventButton() == 0 && Mouse.getEventButtonState()){
//system uses tileTypes because player textures are tiletypes itself, so in the end we can let them swim by changing tiletypes
int xCoord = (int) Math.floor(Mouse.getX() / 64);
int yCoord = (int) Math.floor((HEIGHT - Mouse.getY() - 1) / 64);
tileType tile1 = map[xCoord][yCoord].getType();
System.out.println("first tile is set to:" + tile1);
start = false;
}
}
}
if(!start){
while(Mouse.next()){
if(Mouse.getEventButton() == 0 && Mouse.getEventButtonState()){
int xCoord2 = (int) Math.floor(Mouse.getX() / 64);
int yCoord2 = (int) Math.floor((HEIGHT - Mouse.getY() - 1) / 64);
tileType tile2 = map[xCoord2][yCoord2].getType();
System.out.println("second tile is set to:" + tile2);
}
}
}
I want to change a unicode char inserted using Alt+Unicode code from the keyboard.
I used PretranslateMessage for changing the chars inserted directly from the keyboard and it worked. But with the Alt+Unicode code method it does not.
Here is the code:
Microsoft Word has this functionality when enabling show/hide paragraph marks.
BOOL CEmphasizeEdit::PreTranslateMessage(MSG* msg)
{
if (msg->hwnd == m_hWnd)
{
if (msg->message == WM_CHAR)
{
if (TheApp.Options.m_bShowWSpaceChars)
{
if (msg->wParam == ' ') // This works in both cases Space key pressed or Alt + 3 + 2 in inserted
{
msg->wParam = '·';
}
else if (msg->wParam == (unsigned char)' ') // this does not work
{
msg->wParam = (unsigned char)'°';
}
}
}
}
return CRichEditCtrl::PreTranslateMessage(msg);
}
If I insert from the keyboard Alt + 0 + 1 + 6 + 0 which is ' '(No-Break Space), I want the CRichEditCtrl to display '°' or another char that I specify.
How can I handle this to make it work?
Alt+Space is reserved for program's close menu.
You should use another sequence like Ctrl+Space or Alt+Ctrl+Space
' ' and (unsigned char)' ' are the same thing, therefore the code never reaches else if (msg->wParam == (unsigned char)' '). You should remove that.
Use GetAsyncKeyState to see if Alt or Ctrl key is pressed down.
BOOL IsKeyDown(int vkCode)
{
return GetAsyncKeyState(vkCode) & 0x8000;
}
...
if (msg->wParam == ' ')
{
if (IsKeyDown(VK_CONTROL))
msg->wParam = L'°';
else
msg->wParam = L'+';
}
...
I had to get the cursor position send an append string to the control and then set the selection after the inserted character. When this happens I have to skip CRichEditCtrl::PreTranslateMessage(msg);
BOOL CEmphasizeEdit::PreTranslateMessage(MSG* msg)
{
if (msg->hwnd == m_hWnd)
{
if (msg->message == WM_CHAR)
{
TCHAR text[2];
text[1] = 0x00;
BOOL found = 1;
switch (msg->wParam)
{
case 0x20: text[0] = _C('·'); break;
case 0xA0: text[0] = 0xB0; break;
}
CHARRANGE cr;
GetSel(cr);
cr.cpMax++;
cr.cpMin++;
ReplaceSel(text);
SetSel(cr);
return 1;
}
}
return CRichEditCtrl::PreTranslateMessage(msg);
}
I am writing a text editor using the wxWidgets framework. I need to get the word under caret from the text control. Here is what I came up with.
static bool IsWordBoundary(wxString& text)
{
return (text.Cmp(wxT(" ")) == 0 ||
text.Cmp(wxT('\n')) == 0 ||
text.Cmp(wxT('\t')) == 0 ||
text.Cmp(wxT('\r')) == 0);
}
static wxString GetWordUnderCaret(wxTextCtrl* control)
{
int insertion_point = control->GetInsertionPoint();
wxTextPos last_position = control->GetLastPosition();
int start_at, ends_at = 0;
// Finding starting position:
// from the current caret position, move back each character until
// we hit a word boundary.
int caret_pos = insertion_point;
start_at = caret_pos;
while (caret_pos)
{
wxString text = control->GetRange (caret_pos - 1, caret_pos);
if (IsWordBoundary (text)) {
break;
}
start_at = --caret_pos;
}
// Finding ending position:
// from the current caret position, move forward each character until
// we hit a word boundary.
caret_pos = ends_at = insertion_point;
while (caret_pos < last_position)
{
wxString text = control->GetRange (caret_pos, caret_pos + 1);
if (IsWordBoundary (text)) {
break;
}
ends_at = ++caret_pos;
}
return (control->GetRange (start_at, ends_at));
}
This code works as expected. But I am wondering is this the best way to approach the problem? Do you see any possible fixes on the above code?
Any help would be great!
Is punctuation part of a word? It is in your code -- is that what you want?
Here is how I would do it:
wxString word_boundary_marks = " \n\t\r";
wxString text_in_control = control->GetValue();
int ends_at = text_in_control.find_first_of( word_boundary_marks, insertion_point) - 1;
int start_at = text_in_control.Mid(0,insertion_point).find_last_of(word_boundary_marks) + 1;
I haven't tested this, so there likely are one or two "off-by-one" errors and you should add checks for "not found", end of string, and any other word markers. My code should give you the basis for what you need.