How to add Score to a game - java

I am trying to add a score feature to my game. I know that where I have a remove function I now need to add code which means that whenever an enemy is removed it contributes to the score of the game but I don't know how to implement that into my game using code. Below I have included relevant code.
boolean alive() {
for (int i = 0; i < bullets.size(); i++) {
Bullet bullet = (Bullet) bullets.get(i);
if (bullet.x > x && bullet.x < x + pixelsize * 7 && bullet.y > y && bullet.y < y + 5 * pixelsize) {
bullets.remove(i);
bullet.alive = false;
return false;
}
}
for (int i = 0; i < bullets.size(); i++) {
Bullet bullet = (Bullet) bullets.get(i);
if (bullet.alive == false) {
bullets.remove(i);
}
}
return true;
}

Step 1: Create an int score variable at the sketch level.
int score = 0;
Step 2: Increment that variable whenever you want to increase the score.
score += 100;
Step 3: Display that score in the draw() function whenever and wherever you want the score to be displayed.
text("Score: " + score, 20, 20);
Also, I noticed that you're comparing String values with the == operator. Don't do that. Instead, use the equals() function:
String x = "test";
if(x.equals("blah")){
//whatever
}

You didn't mention if you'd like the score to be permanent or not. If so, you could write the scores to a simple csv file to get a leaderbord. Eaven a normal texfile would do.

Related

I get "IndexOutOfBounds" in my Comets vs Spaceship Game

I began developing a "Spaceship vs Comets" style game last week and now I have come to a stop.
The purpose of the game is to shoot the comets before they pass your ship. You make the comets explode by firing at them. Simple idea!
However, sometimes when I play I get the "IndexOutOfBounds" error. It almost always appears when I haven't fired for a while (The size of my shots ArrayList is 0) and when I then fire and it collides it crashes.
So I have some kind of error in my code, but I really can't see it. I now hope that one of you might see why this accurs and save me from further "IndexOutOfBounds" errors! :)
Here is the part of the code that fails, including the functions that I use to move the comets and shots:
GAME CLASS
if(!Game.player.getShots().isEmpty() && !comet.getComets().isEmpty()) { //Om de är tomma så ignorera
for(int x = 0; x < Game.player.getShots().size(); x++) { //Shots X
if(!comet.getComets().isEmpty() && !comet.getComets().isEmpty()) {
for(int y = 0; y < comet.getComets().size(); y++) { //Comets Y
if(comet.getComets().get(y).intersects(Game.player.getShots().get(x)) && !comet.getComets().isEmpty() && !Game.player.getShots().isEmpty()) {
//the for loop above is the line that won't compile sometimes
comet.getComets().remove(y);
Game.player.getShots().remove(x);
score++;
}
}
}
}
}
//Comet spawn timer
comet.addComets();
//Move the comets and shots!
Game.player.moveShots();
comet.moveComets();
repaint();
COMET CLASS
public ArrayList<Rectangle> getComets() {
return comets;
}
public void moveComets() {
if(!comets.isEmpty()) {
for(int x = 0; x < comets.size(); x++) {
comets.get(x).x -= cometSpeed;
}
}
}
PLAYER CLASS (Shots are in this class)
public void fire() {
shots.add(new Rectangle(x + player.width, y + 23, shotWidth,shotHeight));
}
public ArrayList<Rectangle> getShots() {
return shots;
}
public void moveShots() {
if(!shots.isEmpty()) {
for(int x = 0; x < shots.size(); x++) {
shots.get(x).x += fireSpeed;
}
}
}
Keep in mind that comets and shots are both "ArrayList out of the object Rectangle"
I will provide screenshots of error and a picture of the game below!
The error line is marked in the code above, the if statement should block it from crashing (I thought).
Thanks in advance! All help is appreciated! :)
You should change the order at the if statement to avoid it from evaluate one part of it.
You should change your condition to:
if( x < Game.player.getShots().size() && comet.getComets().get(y).intersects(Game.player.getShots().get(x))) {
That's because you're removing a shot and inside the comets for when the shoot is removed at the next comet iteration it will throw IndexOutOfBounds as the array no longer have the shot you're checking at the if, so you'll need to check again for the x existing on shots.
You can also do it at the for, you check for both conditions and you let the intersect as only check at the if.
A better performance if would be:
if(!Game.player.getShots().isEmpty() || !comet.getComets().isEmpty()) {
//if one of them is empty, won't be intersections
for(int x = 0; x < Game.player.getShots().size(); x++) { //Shots X
for(int y = 0; y < comet.getComets().size() && x < Game.player.getShots().size(); y++) {
//Comets Y only if the shoot still available
if(comet.getComets().get(y).intersects(Game.player.getShots().get(x))) {
//the for loop above is the line that won't compile sometimes
comet.getComets().remove(y);
Game.player.getShots().remove(x);
score++;
y = 0; // if you don't set the y = 0 the next shoot (as you removed the x, getShots.get(x) would be the x + 1 shoot) will only evaluate for the comets after y, won't evaluate the firsts comets at the array.
}
}
}
}
Try to adjust here if(!comet.getComets().isEmpty() && !comet.getComets().isEmpty()). You are checking for comet array twice.
Let me know if it works.
Is this code multithreaded?
I am also wondering why you are verifying comet.getComets().isEmpty() so many times.
My guess is that you are manipulating the ArrayList in some other part of your code. Reason I think this is because you are checking the size of the list multiple times and because within the for loop you are only deleting in the end, so that should not be the problem.
For instance if you run this method at two threads at the same time, the ArrayList can be checked at one point, but can reduce after checking the size. then when for instance the size was 10, but became 9, but you still try to delete x with value 10, you will get the out of bounds error.

Collision Detection in processing

I have a processing program with shapes that move across the screen, and lose health when they collide. Like a battle. But the collision detection only works on one set of colliding units at a time. If a battle is happening at a point on the screen, other battles won't happen until that one finishes.
for(int i = 0; i < enemies.size(); i++){
for(int j = 0; j < friendlies.size(); j++){
if(checkCollision(friendlies.get(j),enemies.get(i))){
if(ttime == 0){
ttime = millis();
}
if((millis()-ttime)>1000){
if(enemies.get(i).getXSpeed()==0 && enemies.get(i).getYSpeed()==0){
enemies.get(i).attackfriendly(friendlies.get(j));}
if(friendlies.get(j).getXSpeed()==0 && friendlies.get(j).getYSpeed()==0){
friendlies.get(j).attackenemy(enemies.get(i));
}
ttime=0;
}
}
}
}
boolean checkCollision(friendlyUnit f, enemyUnit e){
if(Math.abs(f.getX()-e.getX()) < 21 && Math.abs(f.getY()-e.getY()) < 21){
return true;
}
else{
return false;
}
}
void attackenemy(enemyUnit e){
int damage=0;
ArrayList<friendlyUnit>friendnear = new ArrayList<friendlyUnit>();
for (int i=0; i< friendlies.size(); i++){
if ((checkCollision(friendlies.get(i),e))&& friendlies.get(i).isAlive()){
friendnear.add(friendlies.get(i));
}
}
for (int j=0; j<friendnear.size();j++){
damage=damage+friendnear.get(j).getAttack();
}
e.changeHealth(damage);
}
enemies and friendlies are arrays of enemy and friendly shapes. The ttime stuff is a timer. getX and getY return X and Y coorinates.
It appears that ttime is a global and is getting checked/reset for all friendly/enemy interactions, rather than each interaction having it's own ttime. Does only 1 attack happen about every second? You need to have an array of ttimes so that a timer is only associated with one interaction, which means an array/ArrayList of size (enemies.size()*friendlies.size()), one for each interaction.

Galton Box; Printing a histogram

Hey guys I'm writing a program for homework to display the path of a ball in a Galton box
My program so far picks how many balls you want to drop, and the amount of slots at the bottom of the box, and the shows you the random path the ball takes.
The problem I've run into is creating a histogram that depicts the end result.
One important piece of information that I found out, is that every time the ball falls to the right, it moves over one position. So if the print statement is LRLRLR it would be in the 3rd slot because of the 3 R's.
An example of a random histogram it could print:
public class Set_8_P6_21 {
public static void main(String[] args) {
// Declaring variables and calling scanner
int balls, slots;
System.out.println("Enter the amount of balls to drop: ");
Scanner input = new Scanner(System.in);
balls = input.nextInt();
System.out.println("Enter the amount of slots: ");
slots = input.nextInt();
char[] arrayslot = new char[slots-1];
int[] arraypattern = new int[slots-1];
// Nested loop that runs the amount of balls through the machine, and through the amount of slots.
for (int i = 0; i < balls; i++) {
System.out.println();
for (int j = 0; j < slots-1; j++) {
double k = Math.random();
if (k < 0.5) {
arrayslot[j] = 'L' ;
arraypattern[j] = 1; // This is where I am trying to make my histogram
}
else if (k >= 0.5) {
arrayslot[j] = 'R';
arraypattern[j] = 0; // This is where I am trying to make my histogram
}
System.out.print(arrayslot[j]);
}
}}}
If anyone has an idea of how could make this print with the information coming from the loop it would be very helpful, thank you for taking your time to read this.
First, there is no real need for you to keep the array arrayslot, because you print the array element right away, and you don't do anything with it afterwards. So you can just print the character:
if ( k < 0.5 ) {
System.out.print("L");
} else {
System.out.print("R");
}
As you notice, there is also no need for an else if. Either k is less than 0.5, or it is greater than it. So you can just use else.
In order to figure out which slot the ball will fall into, you need to count the Rs. To do so, you simply have an int that gets 0 at the beginning of each ball's simulation, and then you add to it when you roll an "R" above. So your loop expands to:
for (int i = 0; i < balls; i++) {
int ballSlot = 0;
for (int j = 0; j < slots - 1; j++) {
double k = Math.random();
if ( k < 0.5 ) {
System.out.print("L");
} else {
System.out.print("R");
ballSlot++;
}
}
System.out.println();
}
But of course, if we just do that, the value doesn't go anywhere and we lose it after we finish simulating the ball. What you want to do is keep an array which keeps the number of times we hit each slot. So at the end of each ball's simulation, when we know which slot it fell into, we add 1 to the given slot. If we hit the same slot 3 times, we'll have 3 in that spot in the array:
int[] frequencies = new int[slots];
// Nested loop that runs the amount of balls through the machine, and
// through the amount of slots.
for (int i = 0; i < balls; i++) {
int ballSlot = 0;
for (int j = 0; j < slots - 1; j++) {
double k = Math.random();
if ( k < 0.5 ) {
System.out.print("L");
} else {
System.out.print("R");
ballSlot++;
}
}
frequencies[ballSlot]++;
System.out.println();
}
Now, in order to print the histogram properly, you have to start from the tallest column, and work your way down until you reach the "floor" of the histogram, printing an O for every slot that has balls at that frequency. For example, if we have 3 balls in slots 4 and 5, and 1 ball in slot 2, you start from 3, the highest frequency:
For frequency 3, print O in the 4th and 5th positions.
For frequency 2, no new positions at this height, but you have to print O in 4th and 5th again, because otherwise you'll have an O only at the top of the column, instead of its whole height.
For frequency 1, you print O in the 2nd, 4th and 5th positions.
So in order to do this, we have to find out which is the highest frequency first. You can scan the array for that, but actually, you could calculate it while doing the simulations already:
int[] frequencies = new int[slots];
int maxFrequency = 0;
// Nested loop that runs the amount of balls through the machine, and
// through the amount of slots.
for (int i = 0; i < balls; i++) {
int ballSlot = 0;
for (int j = 0; j < slots - 1; j++) {
double k = Math.random();
if ( k < 0.5 ) {
System.out.print("L");
} else {
System.out.print("R");
ballSlot++;
}
}
frequencies[ballSlot]++;
if ( frequencies[ballSlot] > maxFrequency ) {
maxFrequency = frequencies[ballSlot];
}
System.out.println();
}
As you can see, if any frequency is greater than what we have currently as maxFrequency, we keep it as our new maxFrequency.
Now, the printing of the histogram:
for ( int i = maxFrequency; i > 0; i-- ) {
for ( int j = 0; j < slots; j++ ) {
if ( frequencies[j] >= i ) {
System.out.print( "O");
} else {
System.out.print( " ");
}
}
System.out.println();
}
For each position where we don't have a ball at this level, we print a space. For a position where we have a ball, we print an O.
The variable i represents the current level or height of the histogram we are drawing. So the condition if ( frequencies[j] >= i ) means If at this position, we have at least as many balls as the current height.
That's it. Add a System.out.println() before the simulation loop and before the histogram loop to space between the input, the simulation and the histogram, and you are done.

Knights tour backtracking Java

I am trying to solve the Knights tour problem on a 4x4 board with backtracking and recursion in java, and on the output I get this step sequence:
1 13 16 15
10 7 4 14
5 2 11 8
12 9 6 3
in the right upper corner, the 14, 15 and 16 neighbour with each other, which is impossible, because the knight moves on the chessboard into an L-shape. I would be thankful if someone could help me solve this.
the code:
public class KnightsTour {
private static int board[][] = new int[4][4];
private static int stepCounter = 1;
public Test() {
initBoard(board);
tour(0,0);
printSol(board);
}
public static void printSol(int[][] a) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
if(a[i][j]>9){
System.out.print(a[i][j] + " ");
}else{
System.out.print(a[i][j] + " ");
}
}
System.out.println();
}
System.out.println();
}
public static void initBoard(int[][] a) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
a[i][j] = -1;
}
}
}
public void tour(int x, int y) {
if (((x < 0) || (x >= 4) || (y < 0) || (y >= 4)) || (board[x][y] != -1)) {
return;
}else{
board[x][y] = stepCounter++;
tour(x+2, y+1);
tour(x+1, y-2);
tour(x+1, y+2);
tour(x-1, y+2);
tour(x-2, y-1);
tour(x-2, y+1);
tour(x-1, y-2);
tour(x+2, y-1);
}
}
public static void main(String[] args){
new KnightsTour();
}
}
You need to make the function return a boolean so it can tell the calling function whether or not it succeeded. Otherwise you just carry on until you've tried every possible combination, even after you've found a solution.
Then, at each call of the function, you need to check the return value and return true if it succeeded.
Then you also obviously need to return true when done.
I suggest something like:
if (stepCounter == 1 + board.length * board[0].length)
return true;
Right after board[x][y] = stepCounter++;.
You need to revert any changes made at the end of the function call, i.e. stepCounter needs to decrease and board[x][y] needs to be set to -1.
After you've successfully made these changes, you should actually see a result of all -1's, because it's not possible on a 4x4 board, but changing it to 8x8 should succeed.
Note that I didn't use 17 above - it's good practice to not use hard-coded values (in, for example, x >= 4). Use either the size of the array, or final values, instead.
Your tour() function appears to set the value of a square to the step-counter of the order it's visited for the first time. But you're trying multiple options. Your first tour dead ends when you get to 12 - one of the subsequent attempts touches each of the 13-16 squares.
You need to store the state of the current tour, rather than the order in which you visited. E.g. if you backtrack, the current square is no longer part of the tour. If you find a tour, you should stop, because you're done.

Java game check if shoot fire touched monster is too slow

I've made a simple game, where you are the box and you are shooting little boxes.
Now to check if the shoot tocuhed the monster, i check if its x is highter or equals to the monster's x, and then i check if its less or equals to the monsters x, and then the same for y.
But the thing is, I have two for loops for this, therefore when I shoot and it touched the monster, the monster will not always get deleted cause the for loop did not reach that monster yet, and im sure it's bad for performance.
IS there a faster way to do this? why is it happening?
private void checkKilled() {
for (int i = 0; i < this.shoots.size(); i++) {
for (int j = 0; j < this.monsters.size(); j++) {
Monster m = this.monsters.get(j);
Shoot s = this.shoots.get(i);
if (s.getX() >= m.getX() && s.getX() <= m.getX() + 15
&& s.getY() >= m.getY() && s.getY() <= m.getY() + 15) {
m.isDead = true;
s.isExploded = true;
}
}
}
}
Not fully understanding the problem, but for performance you can break from inner loop if condition is true; it will then go to next shoot.
...
s.isExploded = true;
break;
}

Categories