How do I create a 2 task for same function using Qt? - c++

I'm playing around with Qt. I am using one ultrasonic sensor, If I start the toy it works fine.
Currently, What am I doing? For example, I have programmed a toy, I will start the toy then it will start walking continuously, If someone is in front of the ultrasonic sensor, then it will sense that and will stop walking. (This is working fine). This is what I have created.
Toystart Thread:
bool Toystart::Limit()
{
if(Dist <= 55)
{
return true;
}
return false;
}
main Thread:
int sensor = 0;
if (toystart->Limit() )
{
if(sensor == 0)
{
toystart->Stop_talking();
delay (5000);
sensor = 1;
break;
}
}
What do I want exactly?
The above-mentioned code working fine, I want to create a more function. For example some person in front of doll that stops talking 5 seconds then it will check again the still Obst there it will stop talking. It needs to check again after 5 seconds if still Obst there It will go to new function there it will say please leave me then after 5 seconds if Obst not there it will walk.

But it is a blocking call. Your function is stuck for 5 seconds, and depending on how delay() is implemented it might make your whole app unresponsive to any other calls and events.
Pseudocode:
if (obstacle is near) {
if (last_operation == "wait") {
last_operation = "Action";
takeAction();
} else {
last_operation = "wait";
wait();
}
} else { // no obstacle
last_operation = "go";
go();
}
Is that what you're looking after?

Related

Else Statement doesn't work in unity?

Alright so here is my code. This should be really simple but it doesn't want to work with me for some reason. Raycast sends a ray from the mouse, if it hits an object with a tag, it assigns a number to a variable. If it doesn't hit an object, then it sets the variable as -99. For some reason mine is hanging on:
A. I don't hit the objects, it outputs -99 the first time but after that it hangs on getting assigned 4.
B.I hit the objects and it will work just fine. After I click OFF the objects it hangs on the variable from the object I just hit previously.
em.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameFunctions : MonoBehaviour {
int Hitnum = -99;
void Start () {
}
void Update () {
if (Input.GetMouseButtonDown (0)) {
objectCheck ();
}
}
//end of UPDATE function
public void objectCheck () {
RaycastHit hit;
Ray ray = camera.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, out hit, 10000.0f)) {
if (hit.collider.tag == "Box") {
Hitnum = 1;
} else if (hit.collider.tag == "Sphere") {
Hitnum = 2;
} else if (hit.collider.tag == "Pyramid") {
Hitnum = 3;
} else if (hit.collider.tag == "Trapezoid") {
Hitnum = 4;
} else {
Hitnum = -99;
}
}
Debug.Log (Hitnum);
}
//end of check
}
Thanks in advance. This is driving me nuts because it should be simple.
EDIT: posted full code this time, yes all of it. I should mention that there are no other objects with tags, it's just null space. This was supposed to be a very basic shape identifier for kids.
EDIT:EDIT: I expect it to put out -99 if you do not hit the object. Later I will probably do something with the numbers but right now I jest need to fix this.
Restarted unity, everything works fine now. Thanks. Looked through my settings to see what had changed. I earlier deleted the background that had a background tag on it. I guess unity decided that if there is not hit on raycast, it will get the object that it last hit?

How do I make a custom event with VTK?

I'm making a thread software with VTK, where I need to change the model itself in real time, while I need to change his method of rendering. Everything is working fine, but, the problem start with the interactor->start(); , the model data gets updated just fine, but it's only showed on screen when I move The camera. Also I have selected some methods for generating a 3D data from a imagedata file, for that I need to close the vtk window (interactor window) and then the code will reopen it and send the new data generated to it...
I would need something like these:
int force close_window = false; int refresh_interactor = false;
I managed to make the Window close, but only with vtkcommand::Keypressed command, but idk how do I do with a new command :S, I tried the vtkcommand::UserEvent but I didn't found a good information about how to deal with that data (like some way to call it)
the way I'm dealing with VTK is with two threads, the first one, is just about the vtk iren loop, and the second one would manage the models and check if iren requires to be updated.
In my dream code it should be something like this:
=======================================================
bool VTKWindow()
{
...
vtkSmartPointer ator = vtkSmartPointer::New();
iren = vtkSmartPointer::New();
RenWindow = vtkSmartPointer::New();
render->SetBackground(.1, .2, .3);
RenWindow->AddRenderer(renderer);
iren->SetRenderWindow(RenWindow);
if(data_type == voxel_type)
{
Render->AddViewProp(VoxelData);
}
else
{
actor->SetMapper(PolyData);
Render->AddActor(Actor);
}
RenWindow->Render();
iren->Start();
}
void ManageVTK()
{
while true loop...
if(force close_window == true)
do some command to exit the iren loop
if(refresh_interactor == true)
do some command to refresh iren
}
Sorry for the english, it's not my native language, and also sorry about the question format, it's the first time I'm using stackoverflow
It may sounds stupid, but, I found a kind of solution for the problem.
I saw on related links this guy vtkRenderWindowInteractor event loop and threading and, it's almost the same problem...
class VTKNewEvent : public vtkCommand{
public:
vtkTypeMacro(VTKNewEvent , vtkCommand);
static VTKNewEvent * New(){
return new VTKNewEvent ;
}
void Execute(vtkObject * caller, unsigned long vtkNotUsed(eventId), void * vtkNotUsed(callData)){
vtkRenderWindowInteractor *iren = static_cast<vtkRenderWindowInteractor*>(caller);
if (iren_close == true){
iren->GetRenderWindow()->Finalize // Stop the interactor
iren->TerminateApp();
iren_close = false;
}
if (iren_update== true){
renderJanela->Render();
iren_update= false;
}
}
};
bool VTKWindow(){
vtkSmartPointer<VTKNewEvent > IrenRefresh= vtkSmartPointer<VTKNewEvent>::New();
...
iren->CreateRepeatingTimer(1);//this makes that IrenRefresh will be called at every 1ms
iren->AddObserver(vtkCommand::TimerEvent, IrenRefresh);
iren->Start();
...
}
it's simple, but, maybe not the best, but it did Th job, I hope this link will help people that are starting into the VTK world, since threads + rendering loop wasn't a simple job to understand what was going on

QGraphicsscene lags with 150+ items

I am not too familiar with the performance of QGraphicsScene and QGraphicsView.. I know that there is a 10 000 chips example which works well and that the QGraphicsScene is optimized for having a large amount of items in it. However, the game I made lags.( I need to note that this is my first game which actually could be called as such )
My mainloop processing looks like this:
timer.setInterval(0);
timer.start();
connect(&timer, SIGNAL(timeout()), this, SLOT(mainloop()));
inside this mainloop I update all my game logic. Everything seems to be ok, but once I go to fullscreen and I have about 100+ Items in the scene..it starts to lag and the completion of the mainloop takes (sometimes) more than 33ms. Besides the Player, I have only Objects of GameCollectable, you can see the update routine in the code below. Is this because I have my mainloop on the GUI Thread? Because every GameCollectable is rendered by an image? Should I try to make the mainloop in its own thread?
It would be really gentle of you, if someone could take a look at the update routine of my GameCollectable class and tell me why my code produces so much lag. I have a I5 2500K processor btw.
void GameCollectable::update(int t)
{
//animationstuff
if(t>lastframeupdate)
{
if(m_spawner!=NULL)
{
if(animindex>=m_spawner->animation_collectable_normal.get()->animationimgs.size()-1)
animindex=0;
m_graphicsitem->setImage( m_spawner->animation_collectable_normal.get()->getFrameImage(animindex));
lastframeupdate=t;
//animindex++;
}
}
if(started==false)starttime=t;
started=true;
move(t);
}
bool GameCollectable::move(int t)
{
float t_inc=(t-starttime)/animtime;
//reached our destination?
if(m_graphicsitem->pos().x()<destPos.x())
{
onDestination=true;
emit signal_reached(this);
return false;
}
//collided with player?
else if(m_graphicsitem->collidesWithItem(Game::GameManager::instance()->getPlayer()->getGraphicsItem()))
{
Game::SoundManager::instance()->playCoinPickup(t);
bumpedPlayer=true;
emit signal_bumped(this);
return false;
}
else
{
m_graphicsitem->setPos(lerp(startPos.x(),destPos.x(),t_inc),m_graphicsitem->pos().y());
return true;
}
return false;
}

How to detect whether a player drops below a certain Y level

I'm trying to write bukkit plugin and one of the features I would like to add is when a player drops to Y level 8 or lower it runs a command on that player. My current case is I'd like to teleport them to other coordinates if they drop to Y level 8 or lower.
Is there a lite way of doing this without have a command run on every "move" event getting each players location then getting their y position then checking if it's less than 9? cause that seems like it would be a lot of work on the server if there are many people moving around.
There is a simpler way to do this without using runnables. Simply use a PlayerMoveEvent.
#EventHandler
public void onMove(PlayerMoveEvent event) {
if (event.getPlayer().getLocation().getY() <= 8) {
event.getPlayer().teleport(event.getPlayer().getLocation().add(0, 100, 0));
}
}
You could always use the SyncRepeatingTask. Then loop through all online players and check if their Y coordinate value is less than 9:
plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
public void run() {
for (Player player: Bukkit.getOnlinePlayers()) { // Loops through all online players
if (player.getLocation().getY() < 9) {
// The player's Y is below 9. Do whatever you want here. For example:
player.teleport(player.getLocation().add(0, 100, 0)); // Teleports the player 100 blocks above where they are
}
}
}
}, 50L, 50L); // Run every 2.5 seconds (50 ticks)
Just make sure to put the above code in your onEnable(), or a method that's called when your plugin is enabled.
If you want to change the repeat time dynamically based on the online players, you could use:
public void runTeleportTask() {
long time = Math.round(Bukkit.getServer().getOnlinePlayers().length / 10) + 10;
/*
Tweak the delay however you like, above we get the online players, and divide it by 10 then
add ten. We're adding 10 because you don't want to end up with a task that runs every
tick in this case... The fastest it would be needed would be every 10 ticks.
So if there were 100 players online, it would get 100/10 = 10, 10+10 = 20 = 1 second,
and if there were 250 players online, it would get 250/10 = 25, 25 + 10 = 35 = 1.75 seconds
*/
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
public void run() {
for (Player player : Bukkit.getOnlinePlayers()) {
if (player.getLocation().getY() < 9) {
player.teleport(player.getLocation().add(0, 100, 0));
}
}
runTeleportTask();
}
}, time);
}
Then all you have to do is invoke runTeleportTask() in your onEnable() method.

Invoke a method only once from a class

I have a shape class in which there is a method (hitTest(int,int)) that continuously checks if the mouse is inside its bounds or not. In another method, I keep on checking if the mouse has stayed there for more than 1 sec.
If it has, trigger a function (by notification/event) that runs animation
It it has not, then don't trigger the animation
If it has already triggered the animation and the animation is running but the mouse leaves the area during this, trigger an interrupt function (by notification/event)
//OnLoad _initHover = false;
void update() //called continously in the application per frame
{
if(hitTest(getMouseX(), getMouseY())){
if(!_initHover){
_initHover = true;
_hoverStartTime = getCurrentTime(); //start hover time
cout<<"Start hist test\n";
}
//If it has hovered over the video for 1.0 sec
if((ofGetElapsedTimef() - _hoverStartTime) > 1.0){
cout<<"Hitting continously for 1 sec\n";
notificationCenter->postNotification(new AnimationStartNotification);
}
}
else{
_initHover = false;
notificationCenter->postNotification(new AnimationInterruptNotification);
}
}
The above code runs fine but there's a logical issue I am facing while trying to use. There are multiple instances of the above Shape class and each class consequently has their update() method as well. The mouse cursor has which has animationStarthandler and animationStophandlers is a single class in the whole application.
Issue 1: So, even when one of the shape just notifies the animationStarthandler to fire, the other shape classes on which hit test is false set the animation to interrupt and the animation does not run.
Issue 2: When the hit test succeeds and the cursor has been in the area for more than 1 sec, the hit test will keep on sending the notification to start the animation (anim's duration 1.5 sec approx.) How do I restrict the hit test to fire the animation only once and keep on firing the same animation again and again?
If in the main method of my application, I directly try to fire the animation by calling the method playAnimation in the pointer class, I get the required result. But I want to give this hover timing and animation functionality to the ShapeClass itself. Any suggestions?
I think that you should consider adding a new boolean, which holds the information of the triggering of the animation (called in the code sample _animationTriggered). This prevents shapes that have not triggered the animation to stop it and the animation that triggered it to make it several times.
if(hitTest(getMouseX(), getMouseY()))
{
if(!_initHover)
{
_initHover = true;
_hoverStartTime = getCurrentTime();
cout<<"Start hist test\n";
}
if((ofGetElapsedTimef() - _hoverStartTime) > 1.0)
{
if (!_animationTriggered)
{
cout<<"Hitting continously for 1 sec\n";
notificationCenter->postNotification(new AnimationStartNotification);
_animationTriggered = true;
}
}
}
else
{
if ( _animationTriggered )
{
_initHover = false;
notificationCenter->postNotification(new AnimationInterruptNotification);
_animationTriggered = false;
}
}
Don't forget to initialie this new boolean in the same place as _initHover