So I am making a game where there are waves of enemies. The Wave class contains an update method that updates all the enemies in an arraylist of enemies contained in the Wave class. The Wave class also has a boolean called beat that decides whether or not the player has beaten the current wave. I am now have been trying however to start the next wave after the player beats the first. All waves in the arraylist start out with their beat variable as true except for the first. There are currently only two waves. I do not know why this is not working. Thank You for any help.
for(int i = 0; i < 1;i++)
{
if(!w.get(i).beat)
w.get(i).update(g2d);
else if(w.get(i).beat)
{
if(i-1 != -1)
{
if(w.get(i-1).beat && w.get(i).beat)
{
w.get(i).beat = false;
}
}
}
}
Your loop will increment i to the next wave after setting the current wave's beat setting to false, and miss calling the update method for that case. It looks like you should either call its update method immediately after setting beat = false, or perform the if test in the opposite order like this:
for(int i = 0; i < numWaves;i++) // upper range should be the number of waves
{
if(w.get(i).beat)
{
if(i>0) // this can be simplified to "if (i>0)"
{
if(w.get(i-1).beat) // no need to check w.get(i).beat here
{
w.get(i).beat = false;
}
}
}
else
w.get(i).update(g2d);
}
I don't know why you'd initialize a wave's beat state to true then set it to false when its turn comes. Why not just initialize all to false since they really haven't been beat yet?
I'm not sure that I understand your code but I can tell you 2 things. First of all, your loop never loops because as soon as the index is 1, it ends without executing the code a second time. Secondly
if(i-1 != -1)
{
if(w.get(i-1).beat && w.get(i).beat)
{
w.get(i).beat = false;
}
}
is always false due to what I said.
Related
I tried to do this LeetCode daily challenge but I've found out that my code loops infinitely.
I looked through it multiple times, but I cannot find where the problem is. If anyone could spot it, please answer.
public int longestValidParentheses(String s) {
int count, highestOne = 0, index = 0;
boolean isSevered = false;
boolean theEnd = false;
while(!theEnd) {
count = 0;
while(!isSevered) {
if(index<s.length()-2) {
if(s.charAt(index) == '(' & s.charAt(index++) == ')') {count = count + 2;index = index+2;}
else {isSevered = true;}}
else theEnd=true;isSevered=true;
}
highestOne = count;
}
return highestOne;
}
I have 2 suggestions for you:
Use indentation and do not write if/else on the same line as the code associated with them
Always, ALWAYS use bracelets, even if you have only a single command. I think one of the wrongs java did is letting the programmers the free not to use bracelets if there is just a single command after it. It confusing.
So you have 2 mistakes here that make your code run for infinity:
isSevered will always be true after one loop exactly, as you change it to true no matter what happens as it is outside the if else statements, hence the reason I wrote the 2 advices above.
You never changing isSeveres or theEnd at the outside loop. Meaning that if isSevers is true and theEnd is false, you will never enter the internal while and will never exit the outside while.
The two of those combined means that if the condition that make theEnd be initialized with true won't happen at the first run, you will be stuck with infinity loop.
I'm creating a game (Java) with scene2d.
I wrote function for collision detection but I think it's bad function. It looks bad.
How can I optimize it? Make faster and more beautiful.
private void deleteEnemies()
{
for(int i = 0; i < getActors().size - 1; i++)
{
if(getActors().get(i) != null && getActors().get(i) instanceof Enemy)
{
////////////////
for (int j = 0; j < getActors().size - 1; j++)
{
if(getActors().get(j) != null && getActors().get(j) instanceof Ball)
{
if (actorsIntersecting(getActors().get(i), getActors().get(j)))
{
getActors().get(i).remove();
getActors().get(j).remove();
}
}
}
//////////////
}
}
}
Put getActors().get(i) in a variable, dont call it twice in the outer if
Same for getActors().get(j) in the inner if
use these variable in the most inner if's condition and body
save the size in a variable because now the .size function is being called on every iteration when the for condition is checked
You shouldn't use a size that can dynamically change during the loop for the loop condition (because you are removing items as you go) which brings us back to #4.
Other than that its pretty much ok coding style perspective and I doubt you can make it more efficient than with what I told you (Other than using threads)
Since you will do this frequently, consider storing the Enemies and Balls in their own structures (List or Set or whatever works). That prevents you from looping through actors you don't need, and avoids the instanceof checks.
Well, my first idea was to check only "nearest" enemies and not all of them. Somehow try to decrease size of that list.
2. Second one - please check your and conditions in and one by one - now you are checking 2 conditions always. Try to put "heavier" if later, for example:
from:
if(getActors().get(i) != null && getActors().get(i) instanceof Enemy)
to:
if(getActors().get(i) != null) {
if(getActors().get(i) instanceof Enemy) {
.....
}
}
3. call your getActors().get(i) one time - save to variable.
4. I'm thinking why is it necessary to check if an actor is null, maybe just remove nulls from list or keep uninitialized actors on another list. Also try this with Balls and Enemies, please don't keep every actor on a single list.
I would rewrite the models a bit, so they can test the intersection itself and then do the delete like that (probably it can still be improved)
private void deleteEnemies () {
List<Actor> actors = getActors();
List<Actor> toRemove = new ArrayList<Actor>();
int actorsSize = actors.size();
Actor first = null, second = null;
for(int i = 0; i < actorsSize; ++i) {
first = actors.get(i);
for(int j = 0; j < actorsSize; ++j) {
if(i == j) continue;
second = actors.get(j);
if(first.intersects(second)) {
toRemove.add(first);
toRemove.add(second);
}
}
}
actors.removeAll(toRemove);
}
Don't use size(), define a variable
Try not to cast. Try not to uae instanceof.
Maybe, sort lists by zsort or the like so u can, sometimes, start and or stop the loops sooner??
Adding to the (very good) suggestions of the other participant: cache the enemies and projectiles in separate structures, so you don't have to check what they are at all.
Use the time vs space trade-off as much as you can: the standard approach, as hinted by Tomek, in this kind of situations is to reduce the number of checks (=iterations) by pruning the enemies and projectiles that cannot possibly collide within the current frame (they are way to far).
Anyway, a word of advice: go on with the game, complete as much as you can so that it will run correctly (if slowly), and only then go for the optimization.
That because
by optimizing preemptively in this way you will never finish it
you don't know how the final game really will be, perhaps: maybe after finishing 90% of it, you will see some easy chances for optimization.
As others have said, the real improvement to speed would be two collections, one with balls and the other with enemies. As for making it look nicer, you could something like this:
for (Actor enemy : getActors()) {
if (enemy != null && enemy instanceof Enemy) {
for (Actor ball : getActors()) {
if (ball != null && ball instanceof Ball && actorsIntersecting(enemy, ball)) {
ball.remove();
enemy.remove();
}
}
}
}
So some background information, I'm new to programming and am still learning, so I apologize for my trivial error making. I am making my own text based game just to further practice etc.
Here is the link to everything on dropbox for more context:
https://www.dropbox.com/sh/uxy7vafzt3fwikf/B-FQ3VXfsR
I am currently trying to implement the combat system for my game, and I am running into the issue of the combat sequence not ending when required. The 'combat sequence' is a while loop as follows:
public void startCombat()
{
inCombat = true;
while(inCombat != false)// && herohealth > 0 && monsterhealth > 0)
{
checkAlive();
heroHitMonster();
checkAlive();
monsterHitHero();
}
attackinghero.setHeroHealth(herohealth);
attackedmonster.setMonsterHealth(monsterhealth);
}
where the checkAlive() method is as follows:
public void checkAlive()
{
if(herohealth <= 0)
{
System.out.println("You have died.");
attackinghero.clearInventory();
inCombat = false;
}
else if(monsterhealth <= 0)
{
System.out.println("You have killed the "+attackedmonster.getmonsterName()+"!");
inCombat = false;
combatlocation.removeMonster(attackedmonster.getmonsterName());
}
else
{
//
}
}
I am trying to get it to end the combat sequence when either the 'hero' or 'monster' health become <= 0,
however it is currently finishing the while loop and therefore producing the result of the hero being hit even if he killed the monster in his first hit.
This is what is currently being 'printed to screen'
rat loses 5 health!
You have killed the rat!
Hero loses 1 health!
Any help is much appreciated, thanks in advance.
checkAlive shouldn't be void it should be Boolean and should return inCombat, and in your function startCombat you should do inCombat=checkAlive();
The while loop will only evaluate after both actions. You need a way to break the loop after the hero hits the monster. I would personally change the checkAlive method to return a boolean, and put the hit methods in if statements in the while loop:
if(checkAlive())
{
heroHitMonster();
}
if(checkAlive())
{
monsterHitHero();
}
You should end the loop at the end of the checkAlive instead of changing the boolean value.
If you killed the monster at first hit, you still execute the monsterHitHero() even, if the monster is killed. The function to hit should be conditioned to the life of heroes/monster.
I'm making a game where there is a goalie. i want him to move back and forth forever. i have an int called goalieposx (goalie position on the x axis) and i want this is go up by 1 until it hits 200, then go down by one till its back a 0 and repeat. I've tried the folllowing
//this bit isnt in the method, its outside as global varibale
boolean forward=true
//this bit is in a method which is continiouly called nonstop
if (goalieposx<200){
forward=true;
}
else if (goalieposx>200){
forward=false;
}
System.out.println(forward);
if(forward=true){
goalieposx++;
System.out.println("forward");
}
else if (forward=false){
goalieposx--;
System.out.println("backwards");
}
}
this method is called continously. It prints true until it gets to 200, then it prints false. However, it always prints forward, never backward. So conclusion is: the boolean changes as expected but the first if is always called, it seems to ignore the condition
ive also tried this
if(forward = true){
if(goalieposx==200){
forward=false;
}
else{
goalieposx++;}
}
else{
if(goalieposx==0){
forward=true;
}
else{
goalieposx--;}
System.out.println(goalieposx);
}
but this doesnt work either, it prints 1 then 2 etc upto 200 then prints 200 forever. Anyone know how i can solve this? is an if statement the wrong idea altogether?
This is why you should never do comparison for boolean types in if, while, for, whatever. You have just done the assignment in your if statement:
if(forward=true)
the above if statement will always evaluate to true. The problem with this is, this compiles successfully in Java, as syntax wise it's alright. Compiler just checks the type of expression in if evaluates to boolean or not. And it does, so it's ok with it.
You need to do the comparison:
if(forward==true)
.. but as I said, you should not do comparison for boolean types. So, simply doing this:
if(forward)
would be enough.
You also don't need those else if in both the conditions. Just an else will work fine. Well, I don't understand the use of boolean variable at all. It seems like you don't need it. You can change your code to:
if (goalieposx<200){
// forward=true;
goalieposx++;
System.out.println("forward");
}
else {
// forward=false;
goalieposx--;
System.out.println("backwards");
}
What you were previously doing is, setting a boolean variable, based on a condition, and using that boolean variable as condition to execute another if-else block. Well, whatever you are executing in the 2nd if-else block, can simply be moved in the original if-else block, without taking the help of the middle-actor boolean variable.
if(forward=true) does not do what you thing it does.
In java = is the assignment operator and == is the comparison operator. What you are doing with that statement is saying "if assign forward to true" which will set forward to true and always return true.
What you mean to say is if(forward) and if(!forward).
In fact you don't need the else if just an else as if the boolean is not true it must be false.
A better way to do it is to get it to move to the left by adding a minus number, and to the right by adding a positive number. Here's an example of doing this with a loop:
for(int i = -10; i < 100; i++) {
xPosition += i;
}
This would add -10 then -9 etc. to the position.
In your if statements, you need to put two equal signs to check for equality.
if (forward == true){
// execute code
}
EDIT 1:
if (forward)
would be much simpler.
First let's examine what you have already written:
if (goalieposx<200){
forward=true;
}
else if (goalieposx>200){
forward=false;
}
The problem with this code being first is that it while it might set the direction to false once 'goalieposx' has reached 201, in the next call, it will set the direction back to true.
Instead, try using this clever alternative:
//This goes before the infinite loop method
counter = 0;
//Then in the infinite loop method
counter++;
if(counter > 100) {
counter = -100;
}
goalieposx = 100 + counter; //(this shifts counter from
// between -100 and 100 to 0 and 200)
The problem is you are setting the direction based on the value of the integer, instead of whether a condition has previously been met. Try this:
//this bit is in a method which is continiouly called nonstop
if (forward && (goalieposx>200)){
forward=false;
}
System.out.println(forward);
if(forward=true){
goalieposx++;
System.out.println("forward");
}
else if (forward=false){
goalieposx--;
System.out.println("backwards");
}
}
If the die shows a 6, the player doesn't move at all on this turn and also forfeits the next turn.
To accomplish this, I have tried an integer type warning marker variable for the player and an integer type time counter variable.
If the die shows 6, I want to increment the warning marker variable by 1 during the first run(and have the while loop do nothing), then keep the value at 1 during the second run (while loop will not work), then lower it back down to 0 for the third run of the while loop (so the while loop will work). The marker will stay at zero unless the die shows a 6 again, after which the same process will repeat.
I have a while loop like this:
while the warning marker is equal to 0 {
Do Stuff
if the die shows a 6, the warning marker increases by 1.
the time counter also increases by 1.
}
How do I manipulate the variables to get the result that I need? Or is my partially complete method absolutely off in terms of logic?
Thanks.
Can u tell me if this works for you?
flag=true;
while condition{
if flag==true{
if die == 6
{
flag=false;
continue;}
}
else { Do STUFF }
} else
{
flag==true;
}
}
I think you want to reword this problem.
This is what I understood. You have a warning marker.
You have a loop that checks whether the marker is 0, if it is then you do something.
If the die is a six, you will increase the warning marker. If its new value is 3, then you will reset it to 0. Meanwhile, the time counter is always increasing.
If this is correct, I think you want something like:
int warningMarker = 0;
int timeMarker = 0;
while (true) {
if (die == 6) {
++warningMarker;
if (warningMarker == 3) {
warningMarker = 0;
}
}
if (warningMarker == 0) {
doSomething();
}
++timeMarker;
}
Java is Object-Oriented Pragramming language. Use this feature.
See following pseudocode and let me know if you have problem in undestanding it.
Create a class Player as following:
class Player
{
boolean skipChance = false;
... // Other fields
... //
}
Change your while as following:
while(isGameOn())
{
Player p = getCurrentPlayer();
if( ! p.skipChance)
{
int val = p.throwDice();
if(val == 6)
{
p.skipChance = true;
continue; // control moves to while.
}
// Do stuff
}
else
{
p.skipChance = false;
}
}