Movement of Object in a game in C++ - c++

So I am making a game for a school project. You might be familiar with this one. Its Arkanoid, or the game in which a ball is used to destroy bricks and is deflected on by a platform.
Currently I am stuck at a point. I have got an idea of how to move my platform using _getch(), but when I put in a ball it is also moving on a key press. I cant figure out on how to run it simultaneously with or without any key presses. Or if there is way to skip a key press every time until it is registered.
Here is my code so far. The movement of the ball is not complete it is just a prototype right now. Any help would be appreciated.
I am using a graphics library provided by my school but you can use the C++ graphics library.
#include <iostream>
#include "myconsole.h"
#include "mygraphics.h"
#include <conio.h>
#include <string>
using namespace std;
void rect() {
COLORREF White = RGB(255, 255, 255);
COLORREF Blue = RGB(135, 206, 235);
// x1 y x2 y
myRect(400, 475, 550, 480, Blue, Blue);
_getch();
}
void circle() {
COLORREF Red = RGB(255, 0, 0);
myEllipse(0, 50, 300, 350, Red, Red);
_getch();
}
void moverect() {
COLORREF White = RGB(255, 255, 255);
COLORREF Blue = RGB(135, 206, 235);
char _x;
const char _r = 'd';
const char _l = 'a';
int x1 = 400;
int x2 = 550;
int by1 = 455;
int by2 = 475;
int m = 48;
while (1) {
_x = _getch();
system("cls");
if (_x == _r) {
if (x2 < 970) {
x1 += 10;
x2 += 10;
for (int i = 0; i < 10; i++) {
myRect(x1++, 475, x2++, 480, Blue, Blue);
}
}
else
myRect(x1, 475, x2, 480, Blue, Blue);
}
else if (_x == _l) {
if (x1 > 0) {
x1 -= 10;
x2 -= 10;
for (int i = 0; i < 10; i++) {
myRect(x1--, 475, x2--, 480, Blue, Blue);
}
}
else
myRect(x1, 475, x2, 480, Blue, Blue);
}
myEllipse(463, by1 -= 10, 487, by2 -= 10, White, White);
}
}
int main() {
{
moverect();
return 0;
}
}

Since you seem to be using Windows and Microsoft Visual C++ you could use _kbhit(), which will tell you if a key is pressed. Note that this is not standard C++.
This might look like:
if (_kbhit()) {
_x = _getch();
}
else {
_x = -1;
}
Alternatively, others mentioned threads, although John also noted that _getch() is also not standard C++, but I thought introducing some of the concepts of threads might be helpful.There are multiple ways to do it with threads but I will show what I consider to be the easiest way.
First we will create a class, this is to hide a variable that contains the latest character. We want it hidden so that when it is read from the main thread, the latest character is consumed (set to -1) so that when we next call the function, if another character is yet to be input the function will return -1.
Note that if two threads read and write from a variable at the same time, undefined behaviour occurs, for this reason we are going to use an atomic variable as it is defined when two threads try to access it at the same time. Alternatively mutexes exist, they are slower but allow for more complex types to be locked and unlocked so that only one thread may access them at a time.
class LatestChar {
public:
/// initialize latest character to -1
LatestChar() :
latest_char{ -1 }
{}
/// returns latest character or -1 if there is no latest character
int getLatestChar() {
// get latest character
int temp_latest_char{ latest_char };
// consume latest character (so if this is called again, -1 is returned)
latest_char = -1;
// return latest character
return temp_latest_char;
}
private:
/// equal to latest character or -1 when there is no character to get
///
/// this is atomic because it might be read from the main thread at the same
/// time it is written from the getch thread.
std::atomic_int latest_char;
};
Next we need to create the thread that calls _getch(). This is a member variable and will be declared in the constuctor, where it will start running and getting the latest character and repeating.
class LatestChar {
public:
/// initialize latest character to -1,
/// and starts thread that gets the latest character
LatestChar() :
...,
getch_thread([this] {
while (true) {
latest_char = _getch();
}
})
{}
...
private:
...
/// this thread loops until told to stop, and updates the latest character
std::thread getch_thread;
};
Almost done, we now need to rejoin the thread at the end of the program, we will use another atomic variable, this time a boolean, to represent a flag to say "Hey, we are done getting characters, finish what you are doing and join back up with the main thread.
Note that the getch thread will only check this after it reads a character, so when you close your program you might need to input one more character, the alternative is to call something like std::terminate() which will stop the entire program forcefully, which is probably not desired when it can be avoided.
We will initialize the flag to false in the constructor (make sure it is initialized before the getch thread is, otherwise the getch thread might check the value before it has been set to false. The order is they are initialized is the same order they are declared in the class definition.), check it in the thread, and set it to true in the destructor and then also call the join function which will wait until the thread is finished and connect join it back into main.
class LatestChar {
public:
/// initialize latest character to -1, end thread flag to false,
/// and starts thread that gets the latest character
LatestChar() :
...,
end_thread{ false },
getch_thread([this] {
while (!end_thread) {
latest_char = _getch();
}
})
{}
/// sets end thread flag to true and joins getch thread with main thread
~LatestChar() {
end_thread = true;
getch_thread.join();
}
...
private:
...
/// this flag tells the getch thread to stop, like at the end of a program,
/// _getch() will need to receive a character before this is checked
///
/// this is atomic because it might be read from the getch thread at the
/// same time it is written from the main thread.
///
/// make sure this is initialized before the getch thread begins
std::atomic_bool end_thread;
...
};
Finally, let's instantiate the class and call the function.
// somewhere not in a loop
LatestChar latest_char;
...
// somewhere is a loop
_x = latest_char.getLatestChar();

Related

GetAsyncKeyState constantly active

I am trying to make an autoclicker to mess around with getkeystate and key pressing functions in VS and c++, for some odd reason it will never stop clicking once it is initially clicked. I looked over my code and couldn't find anything wrong with it, i know the issue is gonna be something stupidly small. Heres my code:
#include <iostream>
#include <Windows.h>
using namespace std;
bool click = false;
int x = 0, y = 0, cps;
void gui()
{
cout << "Enter desired clicks per second: ";
cin >> cps;
}
void clicked()
{
while (1)
{
if (GetAsyncKeyState(VK_LBUTTON)) // Left mbutton
{
click = true;
}
else
{
click = false;
}
if (click == true)
{
mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
Sleep(1000 / cps);
}
if (click == false)
{
continue;
}
}
}
int main()
{
gui();
clicked();
}```
You maybe missed to read the documentation about return value of GetAsyncKeyState.
The return value of GetAsyncKeyState is zero for the following cases:
The current desktop is not the active desktop
The foreground thread belongs to another process and the desktop does not allow the hook or the journal record.
And,if the most significant bit is set , the key is down.
So, for checking up, you need to check, if the most significant bit is reset.
[Sorry, I am writing the answer on mobile. So, could not provide source code.]

C++. gtk_window_resize doesn't resize window

I've got class (called BorderWindow) which is in fact wrap around GtkWidget. This class represents border around specific application's window (lets say Terminal window, for instance). Inside of BorderWindow constructor I create timer so every second BorderWindow::ClockTick function is called.
Inside of this function border size (which is actually GtkWidget) is compared with bound application's window (Terminal in our case) and if it differs gtk_window_resize is called. However, if I call then gtk_window_get_size it returns old values.
gboolean BorderWindow::ClockTick(gpointer data)
{
auto that = reinterpret_cast<BorderWindow*>(data);
int x = 0, y = 0;
GtkWindow* pWindow = GTK_WINDOW(that->m_borderWindowHandle);
gtk_window_get_size(pWindow, &x, &y);
DUMPER_INFO("curr size: %dx%d; new size: %dx%d", x, y, that->m_windowRect.width, that->m_windowRect.height); // added for debug
if(x != that->m_windowRect.width || y != that->m_windowRect.height)
{
gtk_window_resize(pWindow, that->m_windowRect.width, that->m_windowRect.height);
that->CreateBorder();
GtkWindow* pWindow = GTK_WINDOW(that->m_borderWindowHandle); // added for debug
gtk_window_get_size(pWindow, &x, &y); // added for debug
DUMPER_INFO("after resize: %dx%d", x, y); // added for debug
}
gtk_window_get_position(pWindow, &x, &y);
if(x != that->m_windowRect.x || y != that->m_windowRect.y)
{
gtk_window_move(pWindow, that->m_windowRect.x, that->m_windowRect.y);
}
gdk_window_invalidate_rect(gtk_widget_get_window(that->m_borderWindowHandle), nullptr, FALSE);
that->m_highlightFrame = !that->m_highlightFrame;
return TRUE;
}
Here is debug output
20-05-19 11:24:40.294 [139856177248000] INFO 1537 %% - static gboolean LinuxBorderWindow::ClockTick(gpointer): curr size: 734x540; new size: 1024x706
20-05-19 11:24:40.295 [139856177248000] INFO 1537 %% - static gboolean LinuxBorderWindow::ClockTick(gpointer): after resize: 734x540
So as you can see, the window wasn't resized.
This code snippet works fine for xfce and Unity DEs, but doesn't work for GNOME (and GNOME classic).
Could anyone explain what I'm doing wrong and how to resize window for GNOME DE?
Thanks.

In GTKMM, on_draw method stops being called after invalidate occurs in separated thread

Using GTKMM, I'm extending the DrawingArea widget with the idea that an external process provides it with images. My CameraDrawingArea will then display the images at the right size using Cairo.
Each time an image arrives, I store it and I call the invalidate method, which eventually ends up in a call to on_draw, where I can resize and display the image.
My problem is the following:
The first 10 or 20 images are displayed as I expected.
After a while, the images keep coming from the provider process, I keep calling invalidate
but on_draw is not called any more.
To show it here, I've simplified the code so that there is nothing external to the class, and no link with other libraries. I've replaced the process providing the images by a method with for-loops, and the display of the image by printing a simple text in the middle of the widget area:
In the constructor I launch a new std::thread to call the doCapture method in the same instance. I also set up a font description, to use it later.
The doCapture method is a silly CPU eater, that does nothing except calling from time to time the refreshDrawing method, as long as keepCapturing is not false.
refreshDrawing invalidates the whole window's rectangle via a call to invalidate.
Gtk's magic is suppose to call on_draw and provide a Cairo context to draw whatever. In my case, for tests purposes, I draw a brownish centered integer.
The class destructor stops the thread by set keepCapturing to false, and waits for termination with a join.
#include "camera-drawing-area.hpp"
#include <iostream>
CameraDrawingArea::CameraDrawingArea():
captureThread(nullptr) {
fontDescription.set_family("Monospace");
fontDescription.set_weight(Pango::WEIGHT_BOLD);
fontDescription.set_size(30 * Pango::SCALE);
keepCapturing = true;
captureThread = new std::thread([this] {
doCapture();
});
}
void CameraDrawingArea::doCapture() {
while (keepCapturing) {
float f = 0.0;
for (int n = 0; n < 1000; n++) {
for (int m = 0; m < 1000; m++) {
for (int o = 0; o < 500; o++) {
f += 1.2;
}
}
}
std::cout << "doCapture - " << f << std::endl;
refreshDrawing();
}
}
void CameraDrawingArea::refreshDrawing() {
auto win = get_window();
if (win) {
win->invalidate(false);
std::cout << "refreshDrawing" << std::endl;
}
}
bool CameraDrawingArea::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
std::cout << "on_draw" << std::endl;
static char buffer[50];
static int n = 0;
sprintf(buffer, "-%d-", n++);
Gtk::Allocation allocation = get_allocation();
const int width = allocation.get_width();
const int height = allocation.get_height();
auto layout = create_pango_layout(buffer);
layout->set_font_description(fontDescription);
int textWidth, textHeight;
layout->get_pixel_size(textWidth, textHeight);
cr->set_source_rgb(0.5, 0.2, 0.1);
cr->move_to((width - textWidth) / 2, (height - textHeight) / 2);
layout->show_in_cairo_context(cr);
cr->stroke();
return true;
}
CameraDrawingArea::~CameraDrawingArea() {
keepCapturing = false;
captureThread->join();
free(captureThread);
}
And this is my header file:
#ifndef CAMERA_DRAWING_AREA_HPP
#define CAMERA_DRAWING_AREA_HPP
#include <gtkmm.h>
#include <thread>
class CameraDrawingArea : public Gtk::DrawingArea {
public:
CameraDrawingArea();
virtual ~CameraDrawingArea();
protected:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
private:
bool keepCapturing;
void doCapture();
void refreshDrawing();
std::thread* captureThread;
Pango::FontDescription fontDescription;
};
#endif
The problem manifests itself as follows:
When starting the application, it faithfully displays 1, 2, 3...
Between 5th and 20th iteration (it's random, but rarely outside these ranges), it stops refreshing.
Because of the cout, I can see that refreshDrawing is called be sure that invalidate is also called, but on_draw isn't.
Also, if I stop the application before it stops refreshing, then it ends up nicely. But, if I stop the application after it stops refreshing, then I see this message below (the ID value varies):
GLib-CRITICAL **: 10:05:04.716: Source ID 25 was not found when attempting to remove it
I'm quite sure that I do something wrong, but clueless about what. Any help would be appreciated.
I also checked the following questions, but they don't seem to be related with my case:
Draw signal doesn't get fired in GTKMM, when derived class doesn't call a superclass's constructor
You can't use GTK methods from any other thread than the one in which you started the GTK main loop. Probably the win->invalidate() call is causing things to go wrong here.
Instead, use Glib::Dispatcher to communicate with the main thread, or use gdk_threads_add_idle() for a more C-style solution.
Based on the answer form #ptomato, I've rewritten my example code. The golden rule is do not call GUI functions from another thread, but if you do, then acquire some specific GDK locks first. That's the purpose of Glib::Dispatcher :
If a Glib::Dispatcher object is constructed in the main GUI thread (which will therefore be the receiver thread), any worker thread can emit on it and have the connected slots safely execute gtkmm functions.
Based on that, I've added a new private member Glib::Dispatcher refreshDrawingDispatcher that will allow threads to safely the invalidate the windows area:
#ifndef CAMERA_DRAWING_AREA_HPP
#define CAMERA_DRAWING_AREA_HPP
#include <gtkmm.h>
#include <thread>
class CameraDrawingArea :
public Gtk::DrawingArea {
public:
CameraDrawingArea();
virtual ~CameraDrawingArea();
protected:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
private:
bool keepCapturing;
void doCapture();
void refreshDrawing();
Glib::Dispatcher refreshDrawingDispatcher;
std::thread* captureThread;
Pango::FontDescription fontDescription;
};
#endif
Then, I've connected the dispatcher to the refreshDrawing method. I do this in the class constructor, which is called during GUI start up and therefore in the main GUI thread:
CameraDrawingArea::CameraDrawingArea():
refreshDrawingDispatcher(),
captureThread(nullptr) {
fontDescription.set_family("Monospace");
fontDescription.set_weight(Pango::WEIGHT_BOLD);
fontDescription.set_size(30 * Pango::SCALE);
keepCapturing = true;
captureThread = new std::thread([this] {
doCapture();
});
refreshDrawingDispatcher.connect(sigc::mem_fun(*this, &CameraDrawingArea::refreshDrawing));
}
Finally, the thread has to call the dispatcher:
void CameraDrawingArea::doCapture() {
while (keepCapturing) {
float f = 0.0;
for (int n = 0; n < 1000; n++) {
for (int m = 0; m < 1000; m++) {
for (int o = 0; o < 500; o++) {
f += 1.2;
}
}
}
std::cout << "doCapture - " << f << std::endl;
refreshDrawingDispatcher.emit();
}
}
And now, this works without further problems.

QProgressDialog bar resets to zero when completes

I am using QProgressDialog which obviously just shows progress and it increments along the way. When it reaches 100%, the progress bar on it resets to zero instead of showing 100% there after.
progress is member variable of the class.
QSharedPointer<QProgressDialog> progress;
It is used in on_clicked event. Note I am using Sleep() for simulation, I know it doesn't belong there. The problem is when it reaches 100%, the progress bar shows zero progress and I want to stick to 100%.
void MainWindow::on_pushButtonConvert_clicked()
{
int numFiles = 10;
progress = (QSharedPointer<QProgressDialog>) new QProgressDialog("Copying files...", "Abort Copy", 0, numFiles, this);
progress->setWindowModality(Qt::WindowModal);
progress->setAutoClose( false );
for (int i = 0; i < numFiles; i++) {
progress->setValue(i);
if (progress->wasCanceled())
break;
//... copy one file
Sleep(500);
}
progress->setValue(numFiles);
}
I figured it out, I had to call:
progress->setAutoReset( false );

Exiting glutFullScreen()

I don't understand why when I press 'f' it enters into fullscreen but does not exit out of full screen. In the beginning of this method I have set bool fullscreen = false;
Here is the code for my toggle:
case 'f': //toggle screenmode
if(!fullscreen){
glutFullScreen();
fullscreen = true;
} else if(fullscreen){
glutReshapeWindow(1200, 900);
glutPositionWindow(0,0);
fullscreen = false;
}
break;
at the top of this method I have set bool fullscreen = false;
Every time you press a key, GLUT will call your keyboard handler. And at the top of your keyboard handler, you create a bool variable named fullscreen and set its value to false. This happens regardless of whether you're in full-screen mode or not. Every time you press a key, this will happen.
If you want to retain a boolean variable that actually tracks whether you're currently fullscreen, then you need to use a global. And you need to not set it at the start of the function. You set it once when you create the window, and you only set it again when you change the fullscreen status of the window.
To restore the original window size
... switch the calling order of ReshapeWindow and PositionWindow to
glutPositionWindow(0,0);
glutReshapeWindow(1200, 900);
Otherwise it will go back to windowed mode, but not adapt to the window size you specified!
The problem is not in the code you posted above as according to glutFullScreen specification the window should exit fullscreen mode once glutReshapeWindow or glutPositionWindow is being called.
at the top of this method I have set bool fullscreen = false;
I bet you set this inside the same function (not as a global variable) rendering the variable always being false when you press f
Instead of defining the bool at the beginning of the method, you have to define a global variable. Otherwise each time that method is called, it will set the fullscreen bool to 0, and think that it's not in fullscreen mode. Also, you may want to take not of euphrat's answer, he makes a valid point about the method organization.
Try this:
case 'f': //toggle screenmode
fullScreen = !fullScreen;
if (fullScreen) {
glutFullScreen();
} else {
glutReshapeWindow(1200, 900);
glutPositionWindow(0,0);
}
break;
While it might not answer the question directly, I found it an excellent place to post a go-to full-screen and exit source code.
Switch and restore full screen with <GL/glut.h>
myGame.c
...
glutSpecialFunc(handleSpecial);
void handleSpecial(int key, int x, int y) {
oglHandleFullScreen(key, x, y);
}
...
If you are looking forward to responding to a keyboard event instead (glutKeyboardFunc), make sure to change the signature of the below oglHandleFullScreen to (unsigned char key, int x, int y).
fullscreen.h
void oglHandleFullScreen(int key, int x, int y);
void oglWindowed(int positionX, int positionY, int width, int height);
void oglFullScreen();
fullscreen.c
#include <GL/glut.h>
#include "fullscreen.h"
int isFullScreen = 0;
int previousPosition[2] = { 0, 0 };
int previousSize[2] = { 100, 100 };
void oglHandleFullScreen(int key, int x, int y) {
if (key != GLUT_KEY_F11) { // Respond to F11 key (glutSpecialFunc).
return;
}
if (isFullScreen) {
oglWindowed(previousPosition[0], previousPosition[1],
previousSize[0], previousSize[1]);
} else {
previousPosition[0] = glutGet(GLUT_WINDOW_X);
previousPosition[1] = glutGet(GLUT_WINDOW_Y);
previousSize[0] = glutGet(GLUT_WINDOW_WIDTH);
previousSize[1] = glutGet(GLUT_WINDOW_HEIGHT);
oglFullScreen();
}
isFullScreen = !isFullScreen;
}
void oglWindowed(int positionX, int positionY, int width, int height) {
glutReshapeWindow(width, height);
glutPositionWindow(positionX, positionY);
}
void oglFullScreen() {
glutFullScreen();
}
In this case, you may want to add a static keyword before the bool to make this variable initialized only once.
A safer approach would be to make fullscreen global, since static local variables may be implemented differently across compilers and c++ standards.
Edit to add code snippet:
static bool fullscreen = false;
This should fix the problem of initializing the variable every call to the function, and by c++11 standard should be thread-safe
(Many compilers may say otherwise. Visual Studio only supported this feature of c++11 in VS2015 according to another question's accepted answer: Is static init thread-safe with VC2010?)
Better option may be using a global variable (Wrapping into a class is not good for this purpose).
Edit: Also, despite being simple in syntax, this c++11 feature is costly when called frequently.(See Cost of thread-safe local static variable initialization in C++11?)
(A key down is not that frequent as drawing vertices at high FPS, though... Do NOT use this when performance-critical...)