Me and a friend of mine are working on a game and basically, we have a hitbox set up where if our character hits it (a spider), the character loses health.
Because we are using a for loop, the inevitable happens, the player loses their health 1 by 1, but so fast the human eye can not see it. Therefore we need a timer, pause, or something for every x amount of time the player is hitting the spider. Here is our code:
if (ResetEntities.spiderObj.intersects(ResetEntities.blueCharacterObj)) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 100; i++) {
if (ResetEntities.blueHealth < 0) {
ResetEntities.blueHealth = 0;
Frame.blueHealthLabel.setText("Health: "
+ ResetEntities.blueHealth);
} else {
ResetEntities.getBlueHealth(ResetEntities.blueHealth - 1);
Frame.blueHealthLabel.setText("Health: "
+ ResetEntities.blueHealth);
}
}
}
In this code we have an if statement to check for intersection. I tried to sleep the script, (I realized 10 is incredibly fast, but 1000 lags horribly, so Thread#sleep isn't the way to go I imagine). Then we have a for statement to run 100 times (being the players health). Then we have an if seeing if the health goes below 0, set back to 0, so the player can't get negative health. If it's not below 0, we do the else and subtract 1 health. But as I said this runs too fast to see.
Any help?
The traditional way - and in my opinion best way - to do it is, to make the wounded character invulnerable until a specific point in time: When the character gets wounded, check the game-timeline (or if you dont have one then the current millis-count) then add a specific time eg 1 second (or the character-dependent recovery-time) and remember that timestamp in the character-object. A gametick that wants to wound a character first checks whether the character is still in hidden invulnerability. This is especially good because typically one doesn't really want multiple threads updating the game-state.
Use Timer for your background process' timing. And use javax.swing.SwingUtilities.invokeLater(Runnable) to update your GUI.
The question is unclear, but are you asking how you can stop the health from going down so quick? If so,this is what I would do:
You should have a int value invincibilityTime and set that to 100 once the player is hit, and then every time your game goes through the gameloop it decreases it by one. Put if(invincibilityTime <= 0) before the (ResetEntities.spiderObj.intersects(ResetEntities.blueCharacterObj)) to check if the invicibility period has expired.
Related
I am learning java and so far I have created a password check using if statements. However I inserted my working String check into a while loop and added Thread.sleep(3000); for a 3 second delay, however once I completed that my GUI just keeps lagging and freezing on one page as if the button was pressed. Can somebody please show me how to make a working example of a code with a String check and after a certain amount of tries a delay to stop the user from trying again?
(here is what I have:)
//var declaration
boolean match = false;
String1 = "hi";
String2 = (I know this is not code but just to omit some code:) userInput
int time = 3000;
int attempt = 0;
//check
while(!match && attempt < (maximumTries+1)){
if(String1.equals(String2)){
System.out.print("match");
}
else if(attempt < 11){
attempt++;
System.out.println("Failed:" + attempt);
}
else{
attempt++;
System.out.println("Please try again later you have:" + attempt + "failed attempts");
try{
Thread.sleep(time);
}
catch(InterruptedException ex) {
Logger.getLogger(PasswordEntry.class.getName()).log(Level.SEVERE, null, ex);
}
time = time + 1000;//1 second more every time
}
}
your code is doing an infinite loop once the first attempt does not match.
in each of the iterations of your loop there is no change at all, aside from incrementing the counter. so the counter just increases forever (with some delays in between).
it seems the reasoning behind your code was that String2 got updated with user input inside the loop not outside. This way, on each iteration you would have a different String2 to compare against.
That's your issue, not the way you delay between attempts (that for sure can be improved in any case).
You should avoid using the Thread.sleep option since it completely freezes the main thread. You could also try creating another thread, which will be frozen and later in gives a callback to the main one. For example through a boolean variable. I'd also agree on the timer solution mentioned by BladeMight.
I have been trying to create a way to recreate the pokemon's "Rolling text" where one letter appears at a time. The problem is being able to create a timer short enough to make it reasonable.
This is what i have tried:
public static void roll(String text) {
int i = 0;
while(i < text.length()) {
try {
Thread.sleep(200); //1000 milliseconds is one second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
System.out.print(text.charAt(i));
i++;
}
}
This will work fine if i set the value in Thread.sleep to anything above 250. The problem is, if i set seconds below 250 then it will wait the entire length of time (If i tell it to wait 100 millisends 100 times, it will wait 10 seconds) before outputting anything.
Im not sure if this is a problem with the type of timer itself or if there is something else at play here.
You can use System.out.flush(); to force the buffer to be written out.
I'm working on project using oximeter.I want to smooth it out so I can use it for calculating hearthbeat. I'm gathering raw data from microphone , I put them in new array, lets say, sData[].
Signal is really crazy and jumps all over the plot as expected, so i tried smoothing it using moving average. So my main code looks something like this.
writeAudioDataToFile();
for (int a = 0; a < sData.length; a++) {
tempAvg += Math.abs(sData[a]);
if (a % numberOfSamplesAveraged == 0) { //Average from x samples
if (myIndex > SAMPLE_SIZE - 1) {
myIndex = 0;
}
tempAvg = tempAvg / numberOfSamplesAveraged;
if (tempAvg > 500) {
newDataArray[myIndex] = 500;
}else{
newDataArray[myIndex] = tempAvg;
} //This is suppose to clear the high peaks.
Log.d("isRecording - Average from " + numberOfSamplesAveraged + " numbers.", "newDataArray[" + myIndex + "] = " + newDataArray[myIndex]);
tempAvg = 0;
myIndex++;
}
}
notifier.notifyObservers();
Log.d("Notifier", "Notifier Fired!");
Thread.sleep(20); //Still experimenting with this value
It looks so messy, but the plot (I'm using AndroidPlot btw) looks good but it is so inaccurate so I can't calculate the hearthrate from it. It has so much "Bounce" in "high" state. I found on internet that some kind of filter (Maybe IIR filter) will do the job. So i just wanna ask you guys how can i achieve a nice smooth chart? Is IIR filter the way to go? Is there any free applet/lib to smoothen it out?
This is my first question here so I'm really sorry if it is badly written.
If you will need any more information to help me, just ask.
Here is a picture how my chart looks like now.
http://oi62.tinypic.com/2uf7yoy.jpg // Cant post images im new here.
This is a lucky one though.
I need smoother output.
Noises, which occur at measurement, have high frequency. You should filter your signal, that is you should retain low frequency part of signal and suppress high frquency part of signal. You can do it, making a low-pass filter. It could be, for example, first-order inertial model. I suggest make a pass-band till ~~10 kHz, since people hear sound from 2 kHz to 20 kHz. Then appriopriate sample time is 0,0001 sec (0,1 ms). Discrete model has following equation:
y[k] = 0.9048*y[k-1] + 0.09516*u[k-1],
where u is a measured vector (directly from microphone, input in our filter),
and y is a vector you want to analyze (so output from our filter).
As you can see,, you can calculate a sample number 1, and you can just assign 0 to the sample number 0. After all, you can try to plot y vector.
I am testing a for-loop for smoothly moving an object on the screen.
int yPosLeft = 339;
int originalYPosLeft = yPosLeft;
for(yPosLeft < 30 + originalYPosLeft; yPosLeft++) {
// Changes the value in the statement
}
However, the loop somehow makes the object's y position go into the negative millions forever and pretty much requires a force quit. Any suggestions?
Update: I was stupid with this. Apologies for #BrainFart #Fixed
Your condition is:
yPosLeft < 30 + yPosLeft
...which will always be true. A value will always be less than 30 plus that same value.
Hence, the loop will continue forever and your object's y position will move forever! (That is, until yPosLeft gets so big that it overflows - but I seriously doubt that's the desired behaviour.)
Every number will always be inferior than itself + any positive number. So the condition is always evaluated to true, and hence your loop runs forever.
You need to rework your loop. You can read more about it here.
Maybe you meant:
int yPosLeft = 339;
for(int i = yPosLeft; i > yPosLeft - 30; i--) {
// Changes the value in the statement
}
but I'm not an Oracle ;) - just guessing
I'm writing code to automate simulate the actions of both Theseus and the Minoutaur as shown in this logic game; http://www.logicmazes.com/theseus.html
For each maze I provide it with the positions of the maze, and which positions are available eg from position 0 the next states are 1,2 or stay on 0. I run a QLearning instantiation which calculates the best path for theseus to escape the maze assuming no minotaur. then the minotaur is introduced. Theseus makes his first move towards the exit and is inevitably caught, resulting in reweighting of the best path. using maze 3 in the game as a test, this approach led to theseus moving up and down on the middle line indefinatly as this was the only moves that didnt get it killed.
As per a suggestion recieved here within the last few days i adjusted my code to consider state to be both the position of thesesus and the minotaur at a given time. when theseus would move the state would be added to a list of "visited states".By comparing the state resulting from the suggested move to the list of visited states, I am able to ensure that theseus would not make a move that would result in a previous state.
The problem is i need to be able to revisit in some cases. Eg using maze 3 as example and minotaur moving 2x for every theseus move.
Theseus move 4 -> 5, state added(t5, m1). mino move 1->5. Theseus caught, reset. 4-> 5 is a bad move so theseus moves 4->3, mino catches on his turn. now both(t5, m1) and (t3 m1) are on the visited list
what happens is all possible states from the initial state get added to the dont visit list, meaning that my code loops indefinitly and cannot provide a solution.
public void move()
{
int randomness =10;
State tempState = new State();
boolean rejectMove = true;
int keepCurrent = currentPosition;
int keepMinotaur = minotaurPosition;
previousPosition = currentPosition;
do
{
minotaurPosition = keepMinotaur;
currentPosition = keepCurrent;
rejectMove = false;
if (states.size() > 10)
{
states.clear();
}
if(this.policy(currentPosition) == this.minotaurPosition )
{
randomness = 100;
}
if(Math.random()*100 <= randomness)
{
System.out.println("Random move");
int[] actionsFromState = actions[currentPosition];
int max = actionsFromState.length;
Random r = new Random();
int s = r.nextInt(max);
previousPosition = currentPosition;
currentPosition = actions[currentPosition][s];
}
else
{
previousPosition = currentPosition;
currentPosition = policy(currentPosition);
}
tempState.setAttributes(minotaurPosition, currentPosition);
randomness = 10;
for(int i=0; i<states.size(); i++)
{
if(states.get(i).getMinotaurPosition() == tempState.getMinotaurPosition() && states.get(i).theseusPosition == tempState.getTheseusPosition())
{
rejectMove = true;
changeReward(100);
}
}
}
while(rejectMove == true);
states.add(tempState);
}
above is the move method of theseus; showing it occasionally suggesting a random move
The problem here is a discrepancy between the "never visit a state you've previously been in" approach and your "reinforcement learning" approach. When I recommended the "never visit a state you've previously been in" approach, I was making the assumption that you were using backtracking: once Theseus got caught, you would unwind the stack to the last place where he made an unforced choice, and then try a different option. (That is, I assumed you were using a simple depth-first-search of the state-space.) In that sort of approach, there's never any reason to visit a state you've previously visited.
For your "reinforcement learning" approach, where you're completely resetting the maze every time Theseus gets caught, you'll need to change that. I suppose you can change the "never visit a state you've previously been in" rule to a two-pronged rule:
never visit a state you've been in during this run of the maze. (This is to prevent infinite loops.)
disprefer visiting a state you've been in during a run of the maze where Theseus got caught. (This is the "learning" part: if a choice has previously worked out poorly, it should be made less often.)
For what is worth, the simplest way to solve this problem optimally is to use ALPHA-BETA, which is a search algorithm for deterministic two-player games (like tic-tac-toe, checkers, chess). Here's a summary of how to implement it for your case:
Create a class that represents the current state of the game, which
should include: Thesesus's position, the Minoutaur's position and
whose turn is it. Say you call this class GameState
Create a heuristic function that takes an instance of GameState as paraemter, and returns a double that's calculated as follows:
Let Dt be the Manhattan distance (number of squares) that Theseus is from the exit.
Let Dm be the Manhattan distance (number of squares) that the Minotaur is from Theseus.
Let T be 1 if it's Theseus turn and -1 if it's the Minotaur's.
If Dm is not zero and Dt is not zero, return Dm + (Dt/2) * T
If Dm is zero, return -Infinity * T
If Dt is zero, return Infinity * T
The heuristic function above returns the value that Wikipedia refers to as "the heuristic value of node" for a given GameState (node) in the pseudocode of the algorithm.
You now have all the elements to code it in Java.