(ncurses) - Does mvwaddch() make calls to wrefresh()? - refresh

I'm working on a small game project and by mere curiosity I commented the line that makes a refresh to the main WINDOW object.
while(game->state)
{
//Move into player
params->mov = player_1;
params->x = player_1->pos_x;
params->y = player_1->pos_y;
params->game = game;
//curs_set(FALSE);
player_1->key_move(params);
//Move into player
mvwprintw(p_info,y, x, "TERRAIN: [%c]", player_1->inplace);
//wrefresh(main_scene); /* THE LINE I DELETED */
wrefresh(p_info);
sleep(TICK);
}
The game ran without problems and player updated its position graphically. player_1->key_move(params) eventually calls wgetch(), mvwaddch(), and mvinch(), nothing else (from ncurses). wrefresh(p_info) was commented after and, as expected, that WINDOW object never updated. I'm wondering if that function calls wrefresh() at some point. There's no direct indication of this in the manual.
If it does, are there alternatives to mvwaddch() that doesn't update the WINDOW object?

According to man wgetch, and I quote:
If the window is not a pad, and it has been moved or modified since the last call to wrefresh, wrefresh will be called before another character is read.
Because this is a game, inside the loop, and more concrete in the routine call to player_1->key_move(params) there are modifications to the WINDOW object. This is why the program is causing such behaviour.
I realised that game logic was depending on state from the WINDOW, so several reads/writes would potentially come in the future. All game logic is to be handled separately.

Related

Qt Parent to delete variable after child has closed

I'm writing an application in C++ using the Qt library. There is a central window (the parent) and all the children are launched when needed. Since a number of these windows can be open multiple times, but display different data, I'm declaring the objects with new. Here is an example of what I've got:
Home_Window.hpp
View_Window *SomeWindow;
Home_Window.cpp
void Home_Window::on_WindowButton_clicked()
{
SomeWindow = new View_Window();
SomeWindow->show();
}
What I want to do, is delete the object, when the window is closed to reduce the memory footprint of the application. I've already been able to delete all of the objects contained in the child window to reduce memory usage, but the core object still lingers, and if, through a single day a user opens and closes 1000's of windows, and each object holds onto 40-50KB of memory, the footprint of the application goes from a couple of MBs of memory to 100's of MBs of Memory.
I've not been able to find a guide online that would allow me to achieve this. I was considering a slot and signal pair, as I know that when a window is closed, it sends the QObject::destroyed() signal. Only issue, is I've not tried to setup a signal and slot pair like this.
Any suggestions are appreciated.
to delete the window when it is closed, you can set the WA_DeleteOnClose attribute on it. Your on_WindowButton_clicked() should look something like:
void Home_Window::on_WindowButton_clicked()
{
View_Window* w= new View_Window();
w->setAttribute(WA_DeleteOnClose);
w->show();
}
This way, you don't have to worry about destroying w yourself, it will get deleted automatically when it is closed.
You need to do two things:
The window's lifetime must be managed even if the window isn't closed.
You can give it a parent that you know will end its life at some point. Or you can use a QScopedPointer or std::unique_ptr.
The window must delete itself when it's closed.
void Home_Window::on_WindowButton_clicked()
{
// parent window flags
// vvvv vvvvvvvvvv
auto window = new View_Window(this, Qt::Dialog); /* 1. */
window->setAttribute(Qt::WA_DeleteOnClose); /* 2. */
window->show();
}
At the very least, you should set the Qt::Window flag. The Qt::Dialog includes the Qt::Window flag, and also declares the window to be a dialog box - that fact has platform-specific interpretation; read more about window flags here.
If your View_Window's API is broken, and it doesn't take the window flags as the 2nd argument to the constructor, you need to set them separately:
window->setWindowFlags(Qt::Dialog);
Every widget should be taking Qt::WindowFlags as the optional, 2nd argument to the constructor, with a default value reflecting the usual use of the window. That's the expectation set by all of Qt's widgets.
You can try to delete the pointer to ViewWindow by using: delete SomeWindow;

Weird bug in Qt application

In my application, I have my re-implemented QGraphicsView checking for a mouseReleaseEvent(), and then telling the item at the position the mouse is at to handle the event.
The QGraphicsItem for my view is made up of two other QGraphicsItems, and I check which one of the two is being clicked on (or rather having the button released on), and handle the respective events.
In my Widget's constructor, I set one of the items as selected by default, using the same methods I used when the items detect a release.
When I debugged, I found that for the LabelItem, select is called without a problem from the constructor (and the result is clear when I first start the application). But, when I click on the items, the application terminates. I saw that I was getting into the select function, but not leaving it. So the problem is here.
Which is very weird, because the select function is just a single line setter.
void LabelItem::select()
{
selected = true;
}
This is the mouseReleaseEvent;
void LayerView::mouseReleaseEvent(QMouseEvent *event)
{
LayerItem *l;
if(event->button() == Qt::LeftButton)
{
l = (LayerItem *) itemAt(event->pos());
if(l->inLabel(event->pos()))
{ //No problem upto this point, if label is clicked on
l->setSelection(true); //in setSelection, I call select() or unselect() of LabelItem,
//which is a child of LayerItem, and the problem is there.
//In the constructor for my main widget, I use setSelection
//for the bottom most LayerItem, and have no issues.
emit selected(l->getId());
}
else if(l->inCheckBox(event->pos()))
{
bool t = l->toggleCheckState();
emit toggled(l->getId(), t);
}
}
}
When I commented the line out in the function, I had no errors. I have not debugged for the other QGraphicsItem, CheckBoxItem, but the application terminates for its events as well. I think the problem might be related, so I'm concentrating on select, for now.
I have absolutely no clue as to what could have caused this and why this is happening. From my past experience, I'm pretty sure it's something simple which I'm stupidly not thinking of, but I can't figure out what.
Help would really be appreciated.
If the LabelItem is on top of the LayerItem, itemAt will most likely return the LabelItem because it is the topmost item under the mouse. Unless the LabelItem is set to not accept any mouse button with l->setAcceptedMouseButtons(0).
Try to use qgraphicsitem_cast to test the type of the item. Each derived class must redefine QGraphicsItem::type() to return a distinct value for the cast function to be able to identify the type.
You also could handle the clicks in the items themselves by redefining their QGraphicsItem::mouseReleaseEvent() method, it would remove the need for the evil cast, but you have to remove the function LayerView::mouseReleaseEvent() or at least recall the base class implementation, QGraphicsView::mouseReleaseEvent(), to allow the item(s) to receive the event.
I have seen these odd behaviours: It was mostly binary incompatibility - the c++ side looks correct, and the crash just does not make sense. As you stated: In your code the "selected" variable cannot be the cause. Do you might have changed the declaration and forgot the recompile all linked objects. Just clean and recompile all object files. Worked for me in 99% of the cases.

Is it bad practice to have nested render loops?

I'm porting a game from Ruby to C++. There is a main render loop that updates and draw the content. Now let's say that during the game, you want to select an item another screen. The way it's done in the original code is to do Item item = getItemFromMenu(); getItemFromMenu is a function that will open the menu and do have its own update/render loop, which mean that during the whole time the player has this other screen open, you are in a nested render loop. I feel like this is a bad method but I'm not sure why. On the other hand it's very handy because I can open the menu with just 1 function call and so the code is localized.
Any idea if this is a bad design or not?
I hesitated to post it on gamedev, but since this is mostly a design issue I posted it here
edit : some pseudo-code to give you an idea:
The usual loop in the main part of the code:
while(open) {
UpdateGame();
DrawGame();
}
now inside UpdateGame() i would do something like:
if(keyPressed == "I") {
Item& item = getItemFromInventory();
}
And getItemFromInventory():
while(true) {
UpdateInventory();
if(item_selected) return item;
DrawInventory();
}
A good way to handle something like this would be to replace the DrawInventory() call with something like InvalidateInventory(), which will mark the current graphical state of the inventory as outdated and request it to be redrawn during the next frame rendering (which'll happen pretty soon after when the main loop gets to DrawGame()).
This way, you can keep running through the main loop, but the only parts of the screen that get looked at for redrawing are the ones that have been invalidated, and during normal gameplay you can invalidate your (2/3)D environment as a normal part of processing, but then inside the inventory you can always mark only inventory assets as needing to be redrawn, which minimises overhead.
The other part of your inner loop, UpdateInventory(), can be a part of UpdateGame() if you use a flag to indicate the current game state, something like:
UpdateGame()
{
switch(gameState)
{
case INVENTORY:
UpdateInventory();
break;
case MAIN:
default:
UpdateMain();
break;
}
}
If you really wanted, you could also apply this to drawing:
DrawGame()
{
switch(gameState)
{
case INVENTORY:
DrawInventory();
break;
case MAIN:
default:
DrawMain();
break;
}
}
But I think drawing should be encapsulated and you should tell it which part of the screen, rather than which separate area of the game, needs to be drawn.
What you've created with your nested render loop is functionally a state machine (as most game render loops tend to be). The problem with the nested loop is that many times you'll want to do the same sorts of things in your nested loop as your outer loop (process input, handle IO, update debug info etc).
I've found that it's better to have one render loop and use a finite state machine (FSM) to represent your actual states. Your states might look like:
Main menu state
Options menu state
Inventory state
World view state
You hook up transitions between states to move between them. The player clicking a button might trigger the transition which could play an animation or otherwise, then move to the new state. With a FSM your loop might look like:
while (!LeaveGame()) {
input = GetInput();
timeInfo = GetTimeInfo();
StateMachine.UpdateCurrentState(input, timeInfo);
StateMachine.Draw();
}
A full FSM can be a bit heavyweight for a small game so you can try a simplified state machine using a stack of game states. Every time the user does an action to transition to a new state you push the state on a stack. Likewise when they leave a state you pop it off. Only the top of the stack typically receives input and the other items on the stack may/may not draw (depending on your preference). This is a common approach and has some upsides and downsides depending on who you talk to.
The simplest option of all is to just throw a switch statement in to pick which render function to use (similar to darvids0n's answer). If you're writing an arcade clone or a small puzzle game that would do just fine.

First mouse movement unexpected using SDL (C++)

I'm working on a c++ project for school, and my implementation at this moment requires mouse input for controlling a ship (It's supposed to be a remake of Tyrian). Everything is working fine, except for the first time I move the mouse, it has an offset depending on where the mouse was when I started the game. I guess this is because I'm using SDL_GetRelativeMouse but how can I prevent it?
You may wish to initialize the mouse to a good known position when the application begins, possibly right before events callbacks are initialized.
Making sure the mouse is within the bounds of the window may also be appropriate. It isn't really relevant to the application outside of its boundaries anyway.
This is what I do to toggle mousegrab in a FPS-type application:
if(event.key.keysym.sym == SDLK_z)
{
if( mouse_grabbed )
{
SDL_WM_GrabInput(SDL_GRAB_OFF);
SDL_WarpMouse( display->w/2, display->h/2 );
SDL_ShowCursor(1);
}
else
{
SDL_ShowCursor(0);
SDL_WM_GrabInput(SDL_GRAB_ON);
int tx,ty;
SDL_GetRelativeMouseState(&tx, &ty);
}
mouse_grabbed = !mouse_grabbed;
}
Consuming a mouse update via the dummy SDL_GetRelativeMouseState() call was the important part.
For the moment I'll just suppress the first time mouse movement is detected. This seems to work, but it seems a rather unprofessional approach.
I use this:
Sdl.SDL_ShowCursor(Sdl.SDL_DISABLE);
Sdl.SDL_WM_GrabInput(Sdl.SDL_GRAB_ON);
e=new Sdl.SDL_Event();
pollOne();
.
.
.
private void pollOne(){
while(Sdl.SDL_PollEvent(out e)==1){
switch(e.type){
case Sdl.SDL_MOUSEMOTION:
float throwAway=((float)e.motion.xrel*headSens);
break;
}
}
}
Basically, when initializing the mouse (grabbing it and making it invisible) call pollOne to throw the first event away. Every event captured hereafter in the main event processing function called by the main loop is with mouse at center screen.

wxProgressDialog somehow keeping app alive after death?

I'm having a strange problem with wxWidgets. I have the following code
MyFrame::OnDoSomeLongThing(...) {
progScreen = new wxProgressDialog(text,text,number,this,wxPD_AUTO_HIDE); // wxProgressDialog *progScreen is class member
doPartOfThing() // calls the update method at the end of it
....
doLastPartOfThing() // again calls update method that pushes value to 100/100
progScreen->Destroy();
}
MyFrame::update() {
progScreen->Update(newValue);
}
Now here's the thing. I can literally comment out the lines relating to progScreen, just let the process go without using a progress dialog, after all is said and done, my apps exits gracefully when I close the main window.
However, just the use of the progress dialog is somehow extending the life of the application. I've tried Destroy(), I've tried simply 'delete progScreen', and both, every time: I'll close the main frame, the process keeps running, and at some point exits with some astronomical number. The only thing I could think might be relevant, is that the doPartsOfThings methods may call boost::this_thread::sleep, because it involves waiting and whatnot down in my model class. But this shouldn't have anything to do with my problem. Or maybe it does... EDIT: I do want to emphasize that progScreen->Update() IS being called from the main (GUI) thread.
So I ask, am I using a wxProgressDialog correctly? If not, how should it be used?
Thanks for your help!
EDIT:
Well... it turns out that removing wxPD_AUTO_HIDE fixed the problem. I'm still not quite sure what the problem is, but the dialog even still behaves as before. App closes as expected.
I think that you need to override the wxApp method that closes the application so that it closes the wxProgressDialog object before it quits.
wxApp::OnExit
virtual int OnExit()
Override this member function for any processing which needs to be
done as the application is about to exit. OnExit is called after
destroying all application windows and controls, but before wxWidgets
cleanup. Note that it is not called at all if OnInit failed.
The return value of this function is currently ignored, return the
same value as returned by the base class method if you override it.
You will need something like, assuming progScreen is a public attribute of your frame
int myApp::OnExit()
{
(MyFrame*)(GetTopWindow())->progScreen->Destroy()
return wxApp::OnExit();
}