I know this is a beginner's problem but I cannot progress with my studies until I understand what is going on here. In an if block that I'm executing in Update(), I cannot understand why the two if statements are executed simultaneously. I thought that as soon as the initiative variable was initialized at the start of the block, the compiler would move down to the first if statement to see if the condition is true. If it is true, it would execute the code in that block until the timer reached zero. Then it would move down to the next. If the condition was true in the first, then it would be false in the second so it would move up to the beginning again. A new bool value would be calculated for initiative and the process would be repeated. What's blowing my mind is that no matter what I do, both blocks are executed and the timers are completely ignored. It is very confusing!
I've made some very basic code to highlight the problem I'm having. I'm using this C# code in Unity3d:
public float firstTimer = 2;
public float secondTimer = 10;
public bool initiative;
void Update()
{
initiative = InitiativeOrder();
if(initiative == true && firstTimer > 0);
{
firstTimer -= Time.deltaTime;
Debug.Log ("First timer has finished!");
}
if(initiative == false && secondTimer > 0);
{
secondTimer -= Time.deltaTime;
Debug.Log ("Second timer has finished!");
}
}
public bool InitiativeOrder()
{
float player = Random.Range(1,10);
float enemy = Random.Range(1,10);
if(player > enemy)
{
return true;
}
else if (player < enemy)
{
return false;
}
else
{
return true;
}
}
the reason the timer isnt working is because the ; after your if()
if(initiative == true && firstTimer > 0);<----remove these from your if
make your if() like these
if(initiative == true && firstTimer > 0)
{
firstTimer -= Time.deltaTime;
Debug.Log ("First timer has finished!");
}
if(initiative == false && secondTimer > 0)
{
secondTimer -= Time.deltaTime;
Debug.Log ("Second timer has finished!");
}
its not executing both if() blocks
this code
initiative = InitiativeOrder();
is being called every frame witch is im guessing 60 fps so for every frame per second it is executing that method and the chance however many times per second that it is true or false is why it seems that it is firing both if() blocks but really each frame that update fires its either true or false which is really fast
if you put that call in OnStart() it will only fire once like
void Start(){
initiative = InitiativeOrder();
}
EDIT YOUR CODE
public float firstTimer = 2;
public float secondTimer = 10;
public bool initiative;
void Start(){
initiative = InitiativeOrder();
}
void Update()
{
if(initiative == true && firstTimer > 0)
{
firstTimer -= Time.deltaTime;
Debug.Log ("First timer has finished!");
}
if(initiative == false && secondTimer > 0)
{
secondTimer -= Time.deltaTime;
Debug.Log ("Second timer has finished!");
}
}
public bool InitiativeOrder()
{
float player = Random.Range(1,10);
float enemy = Random.Range(1,10);
if(player > enemy)
{
return true;
}
else if (player < enemy)
{
return false;
}
else
{
return true;
}
}
Related
I'm new to SFML and I have trouble finding a solution to checking if a key is pressed during one frame. The problem I've been facing is the fact that with the Keyboard and Mouse classes, it seems impossible to use a system where one first checks for the current input state before any Update() call of objects and then after all Update() you get a previous input state for the next frame so that one can do the following:
bool Entity::KeyboardCheckPressed(sf::Keyboard::Key aKey)
{
//this part doesn't work
if (KeyboardState->isKeyPressed(aKey) and !PreviousKeyboardState->isKeyPressed(aKey))
{
return true;
}
return false;
}
But this doesn't seem to work with SFML, and other sources tell me that I'm suppose to use the Event class with its type and key.codelike the following example:
bool Entity::KeyboardCheckPressed(sf::Keyboard::Key aKey)
{
if (Event->type == sf::Event::KeyPressed)
{
if (Event->key.code == aKey)
{
return true;
}
}
return false;
}
But this results in the sf::Event::KeyPressed doing the same as KeyboardState->isKeyPressed(aKey), so then I tried the method where you set key repeat to false: window.setKeyRepeatEnabled(false);with no results what so ever. I also found out that the sf::Event::KeyPressed works only as intended inside of this part in the main.cpp:
while (window.pollEvent(event))
{
}
The problem with this is that I want to handle Input inside of my Entity objects' Update()function, and I can't put the whole Update loop inside of the while (window.pollEvent(event)). So here I am, struggling to find a solution. Any help is appreciated.
In general, if you have a thing which you can check the current state of, and you want to check if that state changed between frames, you simply use a variable, declared outside the application loop, to store the previous state, and compare it to the current state.
bool previousState = checkState();
while (true) {
// your main application loop
bool newState = checkState();
if (newState == true && previousState == false) {
doThingy("the thing went from false to true");
} else if (newState == false && previousState == true) {
doThingy("the thing went from true to false");
} else {
doThingy("no change in the thing");
}
// this is done unconditionally every frame
previousState = newState;
}
I'm having a QTimeEdit displaying hh:mm.
This widget behavior is very annoying: When the value is 09:59, there is no easy way to move to 10:00. The spinbox controls on the right only applies to minutes or hours. When you put your cursor on minutes, incrementing is not allowed if value is 59.
To move from 09:59 to 10:00 you need to decrement 59 to 00 and then increment 09 to 10...that's really annoying.
Is there no option to make it possible to let user increment minutes by one using the spinbox control and then get value be changed from 09:59 to 10:00 with a single click??
Set wrapping to true.
As for the automatic change of the hours section, reimplement stepBy in a subclass of QTimeEdit like this:
MyTimeEdit.h
#ifndef MYTIMEEDIT_H
#define MYTIMEEDIT_H
#include <QTimeEdit>
class MyTimeEdit : public QTimeEdit
{
Q_OBJECT
public:
explicit MyTimeEdit(QWidget *parent = nullptr);
void stepBy(int steps) override;
};
#endif // MYTIMEEDIT_H
MyTimeEdit.cpp
#include "MyTimeEdit.h"
MyTimeEdit::MyTimeEdit(QWidget *parent) : QTimeEdit(parent)
{
setWrapping(true);
}
void MyTimeEdit::stepBy(int steps)
{
QTime cur = time();
QTimeEdit::stepBy(steps);
if (currentSection() == QDateTimeEdit::MinuteSection) {
int m = cur.minute();
if ((m == 0) && (steps < 0))
setTime(time().addSecs(-3600));
else if ((m == 59) && (steps > 0))
setTime(time().addSecs(3600));
}
else if (currentSection() == QDateTimeEdit::SecondSection) {
int s = cur.second();
if ((s == 0) && (steps < 0))
setTime(time().addSecs(-60));
else if ((s == 59) && (steps > 0))
setTime(time().addSecs(60));
}
}
I noticed that the above answer does not work when using the mouse wheel or Page Up/Page Down instead of the arrow keys, because then the step is larger than 1 (10 in my case).
Here is a version of MyTimeEdit.cpp that also works with the mouse wheel and Page Up/Down keys:
MyTimeEdit.cpp
#include "MyTimeEdit.h"
MyTimeEdit::MyTimeEdit(QWidget *parent) : QTimeEdit(parent)
{
setWrapping(true);
}
void MyTimeEdit::stepBy(int steps)
{
if (currentSection() == QDateTimeEdit::MinuteSection) {
setTime(time().addSecs(steps*60));
}
else if (currentSection() == QDateTimeEdit::SecondSection) {
setTime(time().addSecs(steps));
}
}
I am following lazy foo's tutorial, however I realized every time I press press s or p, SDL_KEYDOWNtriggers twice. How can this be fixed?
Here is the code snippet:
while(SDL_PollEvent(&e) != 0) {
if(e.type == SDL_QUIT) {
quit = true;
}
else if(e.type == SDL_KEYDOWN) {
if(e.key.keysym.sym == SDLK_s) {
if(timer.isStarted()) {
timer.stop();
printf("stop\n");
}
else {
timer.start();
printf("start\n");
}
}
else if(e.key.keysym.sym == SDLK_p) {
if(timer.isPaused()) {
timer.unpause();
printf("unpause\n");
}
else {
timer.pause();
printf("pause\n");
}
}
}
}
Pressing s once:
start
stop
TL;DR: Check if e.key.repeat equals to 0 before handling the events.
SDL generates fake repeated keypresses if you hold a key long enough. This is used mostly for text input.
The original key press has .repeat == 0, and fake presses have .repeat == 1.
For convenience reasons probably (I'd argue that it's rather inconvenient), since SDL 2.0.5 the actual key press generates two events instead of one. One has .repeat set to 0, and other (new) one has it set to 1.
What would be the best way of counting how many times a bool flag was changed from false to true inside a game update loop? For example if I have this simple example below, where if you hold button "A" pressed the Input class sets the enable bool of the Game class to true and if you release it sets it to false and a counter inside the Game class that counts how many times enable was changed from true to false. For example if you press "A" and release twice counter should update to 2. Having Game::Update() updating at 60fps the counter would be wrong with the current approach. To fix it I moved the check and the counter inside SetEnable instead of the Update loop.
// Input class
// Waits for input
void Input::HandleKeyDown()
{
// Checks if key A is pressed down
if (key == KEY_A)
game.SetEnable(true);
}
void Input::HandleKeyUp()
{
// Checks if key A is released
if (key == KEY_A)
game.SetEnable(false);
}
// Game class
void Game::SetEnable(bool enable)
{
if(enable == enable_)
return;
enable_ = enable;
//Will increment the counter as many times A was pressed
if(enable)
counter_ += 1;
}
void Game::Update()
{
// Updates with 60fps
// Will increment the counter as long as A is pressed
/*
if(enable_ == true)
counter_ += 1;
*/
}
void Game::Update()
{
if (key == KEY_A && ! enable_)
{
enable_ = true;
++counter_;
}
else if (key == KEY_B)
enable_ = false;
}
If I get you right, you want to count how many times enable_ changes. Your code has a small flaw, imagine this example:
enable_ = false
counter = 0
update gets called, key is A -> enable_ = true, counter = 1
update gets called, key is B -> enable_ = false, counter remains 1
Function that might fix this can look, for example, like this:
void Game::Update() {
if (key == KEY_A && !enable_) { // key is A and previous state is false
++counter;
enable_ = true;
}
if (key == KEY_B && enable_) { // key is B and previous state is true
++counter;
enable_ = false;
}
}
I've been studying this thread
Processing 2.0 - Open file dialog
with regard to the use of selectinput().
I'm hoping to import point data to construct some 3d plots.
I can import the data and construct the plot ok but when trying to use
selectinput() to choose a file I run into trouble.
The difficulty I am having is that selectinput() appears to be incompatible with a P3D
window.
Using OS X10.10
for example This code works
void setup() {
size(400, 400,P3D); //3Dgraphics specified
background(0);
stroke(255);
frameRate(20);
}
void draw() {
noFill();
ellipse(mouseX, mouseY, 90, 90);
and this works
String [] myInputFileContents ;
String myFilePath;
void setup() {
selectInput("Select a file : ", "fileSelected");
while (myInputFileContents == null) {//wait
// println("wait"); //If there is nothing inside the curly brackets
//delay(3000); //this doesn't work
size(400, 400 );/// If P3D is added it won't work
background(0);
//smooth();
stroke(255);
frameRate(25);
}
}
void draw() {
box(mouseX, mouseY, 150);
println("Selected at this point " + myFilePath);
}
void mousePressed() {
selectInput("Select a file : ", "fileSelected");
}
void fileSelected(File selection) {
if (selection == null) {
println("no selection so far...");
}
else {
myFilePath = selection.getAbsolutePath();
myInputFileContents = loadStrings(myFilePath) ;// this moves here...
println("User selected " + myFilePath);
}
}
but if
size(400, 400);
is changed to
size(400,400,P3D);
The frame displays but it won't draw.
Could someone point me to the answer?
It seems that this problem is some kind of frame loading problem. This "hackish" approached worked for me under OS X 10.10 Yoesemite. It should also work under windows. Oh and whenever you use selectInput() please use mouseReleased so the function only gets called once :)
Setup() gets called twice for whatever reason, this is why we have the didPreSelect boolean.
You call mousePressed instead of mouseReleased
The loop already had the screen selection in it, this is why i changed the loop.
The delay also has problems, this is why i added the delay inside the while-loop.
Man that was quite the challenge, +1 for asking.
PS: I added an exit() if you press cancel the first time you open the application, which should be more convenient.
String [] myInputFileContents ;
String myFilePath;
boolean didPreSelect = false;
boolean secondPress = false;
void setup() {
if (didPreSelect == false)
{
didPreSelect = true;
selectInput("Select a file : ", "fileSelected");
}
//frame = null;
while (myInputFileContents == null || myInputFileContents.length < 2) {//wait
delay(1000);
}
//this doesn't work
size(400, 400, P3D);
background(0);
//smooth();
stroke(255);
frameRate(25);
}
void draw() {
box(mouseX, mouseY, 150);
//println("Selected at this point " + myFilePath);
}
void mouseReleased() {
if(secondPress == false) secondPress = true;
selectInput("Select a file : ", "fileSelected");
}
void fileSelected(File selection) {
if (frameCount < 50)
{
if (selection == null) {
println("no selection so far...");
if(secondPress == false) exit();
} else {
myFilePath = selection.getAbsolutePath();
myInputFileContents = loadStrings(myFilePath) ;// this moves here..
println("User selected " + myFilePath);
}
}
}