How to get old position of snake body parts in Java - java

I will try my best to explain the issue. So basically I have come to the point in my snake game which I feared the most - the array. So I what I have done is an ArrayList full of Rectangles.
I then add a Rectangle each time I eat the food and I am now at the "looping" part where I have to loop the different rectangles.
I succeded with adding one rectangle to the snake - I just took the old head.x location and the head.y location and but it into the snakeParts.get(0).setLocation.
The problem I am having is drawing the rest of the array (which would be index nr 1 to infinity).
I can't seem to get the rest of the ArrayLists's old positions. For example: I want snakeParts.get(1) to get snakeParts.get(0)'s old position but I can't seem to figure out how to do that logic. I wonder if any of you could give me a hand?
Here is the part of the code that is affected:
repaint();
//Test
for(int z = 0; z < snakeParts.size(); z++) {
System.out.println(z); //Test printing
if(z == 0) {
snakeParts.get(z).setLocation(head.x, head.y); //Printing index 0
}
else {
snakeParts.get(z).setLocation(snakeParts.get(z - 1).getLocation());
//Takes all the indexes and puts them where the snakeParts.get(0) is. I want them to get longer - like the Snake game
}
//Loop different might solve the issue?
}
head.x += speedx;
head.y += speedy;
I am doing this in JPanel and my ArrayList is an array of the Rectangle class which can be found here: Rectangle Class
If you want the entire code - please ask! I thought it would be easier to just show you guys this code sample because it's the only part that affects what I am trying to achieve.
Thanks in advance!

Start from the end and go towards the head, get last part, set its position to where last-1 is.
Then go, for last-1, set its position to where last-2 is.
Repeat that until you reach second part, once you set its position to head, then move your head.
Edit.
Here is how does forward vs backward loop look like:
for(int z = 0; z < snakeParts.size(); z++) {}
for(int z = snakeParts.size() - 1; z >= 0; z--){}
First one starts at 0, goes to size of snake parts by increases of 1.
Second one starts at size of snakeparts - 1 (we decrease by 1 because snakeParts are counted from 0, not from 1), works as long as z is greater-equal to 0, and at each step it reduces z by 1.
Hope that helps :)
In your code you should make sure you are not trying to access indices smaller or larger than the array.

Related

How do you make sure the 2 balls are removed after the collision?

I am a beginner and I am making a space shooter game in Netbeans. I want if the spacecraft's bullet hits the enemy's bullet that the 2 bullets are removed. I have created an Arraylist of bullets and bulletsEnemy. Then I created a method hitByBullet that should ensure that I can search for the bullets that collided. Then in the method bulletsHit (), the bullets should be removed.
My enemies shoot in a loop and don't move. My problem is that the bullets go through each other. The radius of the bullets is 5.
These is the 2 methods that I have written
'''
public int hitByBullet(){
for(int i=0; i<bullets.size(); i++){
for(int j= 0;j< bulletsEnemy.size(); j++){
if( bullets.get(i).getY() - bulletsEnemy.get(j).getY()<= 5)
if(bullets.get(i).getX() -bulletsEnemy.get(j).getX()<= 5){
return i;
}
}
}
return -1;
}
'''
public boolean bulletsHit(){
if (hitByBullet()!= -1){
bullets.remove(this); //with 'this' I refer too 'i'
bulletsEnemy.remove(this);
return true;
}
return false;
}
'''
[This is how it looks like] (https://i.stack.imgur.com/4XsCR.png)
I will try to answer in a way to let you find your way to implement what you want. There are several frameworks out there which will help you with this and as you are new to programming there are a lot of things you could change/do better. But I will ignore these things.
I think your are trying to check if one 5x5 bullet intersects with another 5x5 bullet.
To make it easy let us asume your bullets are squares:
In your hitByBullet you should check your square centers (i asume that are x,y of your bullets) distance in both dimensions:
Sth. like this should check the collision:
if(Math.abs(bullets.get(i).getY() - bulletsEnemy.get(j).getY()) < 5 &&
Math.abs(bullets.get(i).getX() - bulletsEnemy.get(j).getX()) < 5) {
return i;
}
Depending of the size of your bullets you need to change the distance check ( <=5). If your bullets have a size of 5 px it should be < 10. If your bullets are 10x10 you should check against < 20 ...
Regarding a more realistic scenario, that your bullets are circles (e.g. resulting of a 5x5 square px or a radius r=5):
You need to check if the distance between your two bullet centers is smaller than the bullet radius * 2.
That will bring you to use the theorem of pythagoras:
https://en.wikipedia.org/wiki/Pythagorean_theorem
The distance between your bullet centers is c. a is the distance in dimensional x and b the distance in dimensional y. You don't need to take care about negative dimensional values cause you need pow them by 2 which will always give you a positive value.
To check for collision you should calculate the distance c as follows:
c = SquareRootOf(a^2+b^2)
Math.sqrt(Math.pow(bullets.get(i).getX() - bulletsEnemy.get(j).getX()),2) + Math.pow(bullets.get(i).getY() - bulletsEnemy.get(j).getY(),2)) < 10
I think you should read basics about collision detection and geometry. Just two possible points of information:
An easy to start example with code:
https://zetcode.com/javagames/collision/
Circle intersection:
https://www.geeksforgeeks.org/check-two-given-circles-touch-intersect/
Regarding the removal of the bullets I asume you have some kind of game loop in which you frequently draw the bullets and calculate the collision (call the bulletsHit method):
I will make an assumption to make things easier: The movement speed of your bullets is not faster than one pixel per loop. Otherwise I think you need to take care of your loop circle time and calculate the positions of all elements and also take care about bullets that won't intersect in one loop circle because they could have passed by from one loop circle to the next loop circle. I'm not familiar with game dev, so maybe there are more things to cover.
Regarding this you should change things:
The method hitByBullet() will only return one collision per call.
You could store your collidedBullets in two sets and after removing them from your bullets and bulletsEnemy list clear these temporary sets.
I don't understand what you are doing with "this" and your result of
hitByBullet.
I would do it like this
public void hitByBullet(){
for(int i=0; i<bullets.size(); i++){
for(int j= 0;j< bulletsEnemy.size(); j++){
if( Math.sqrt(Math.pow(bullets.get(i).getX() - bulletsEnemy.get(j).getX()),2) + Math.pow(bullets.get(i).getY() - bulletsEnemy.get(j).getY(),2)) < 10){
bulletsToDelete.add(bullets.get(i));
bulletsEnemyToDelete.add(bulletsEnemy.get(j));
}
}
}
}
public boolean bulletsHit(){
hitByBullet();
bulletsToDelete.forEach(bullet -> bullets.remove(bullet);
bulletsEnemyToDelete.forEach(bullet -> bulletsEnemy.remove(bullet);
boolean bulletsHit = !bulletsToDelete.isEmpty();
bulletsToDelete.clear();
bulletsEnemyToDelete.clear();
return bulletsHit;
}
As I mentioned before there are a lots of things you should improve:
general structure of your code
naming of your method (e.g. bulletsHit sounds like only checking if bullets are hit but you are also removing them)
double checking of bullets
Greetings

Create valid coordinates

I'm making a snake game and the apples shouldn't spawn inside the snake when randomly spawned on the screen. I have tried looking for a new place for the apples, when they get placed inside the snake with:
for (int i = 0; i < snake.size() - 1; i++) {
if (snake.get(i).xPos == plum.get(0).xPos && snake.get(i).yPos == plum.get(0).yPos) {
plum.remove(0);
plum.add(new Coordinate(rollDice(squaresX - 1) * (squareSize + sizeOfSpace) + sizeOfSpace, rollDice(squaresY - 1) * (squareSize + sizeOfSpace) + sizeOfSpace, new Color(199, 7, 255)));
}
}
This is not a good solution so I'm looking for a new one where I can create invalid coordiantes which are the snakes coordinates and valid coordinates that is the rest. So I can randomize the apples new position from just valid coordinates. But I'm not sure how I'm supposed to code this
This is just a general suggestion, but I think it might work for you.
Keep the length of the snake updated all of the time
Now when creating a new apple, create an array of Coordinations of size of the grid size minus snake length. For example: if your grid size is 9x9 and your snake length is 6, create an array of length 75.
Run over the grid and array and add to the array just Coordinations that do not have the snake in them. It should look something like this:
int arrayLocation=0;
for(int i=0; i< grid.length();i++)
{
for(int j=0; j<grid[i].length(); j++)
{
if (!snakeAtLocation(i,j))
{
arr[arrayLocation++] = new Coordinate(i, j);
}
}
}
Then you can randomly pick a number n between 0 to arr.length(), then retrieve the coordination from arr[n] and you should have a coordination without a snake in it. Hope it helps and if you need more detailed example I will provide tommorow as I'm writing this from my phone and I don't have pc right now:)
By the way, this answer if for a simple use case, as it isn't optimized and running with o(n)^2 each time you eat an apple. If you want more optimized solutions, you would have to track the snake location with each move he make. I'll be able to post both answers tommorow if needed:)

Discovering a region with no mines on minesweeper

I am new in this page, it hope get to some help, basically I am doing a minesweeper game on Java but it have a problem with a function: discover the region with no mines and no numbers like in the game on windows, when you click in one place and all withe cells appear. I tried make recursive but I can't, some help?
Sorry for the code, the original is in spanish but i tried make a pseudocode:
Matriz = multidimensional Array (the minesweeper)
min and max returns the index min and max to iterate (8 sorroud cells)
private void discoverWitheCell(int x, int y) {
if(matriz[x][y].getdiscovered() == false){
matriz[x][y].setDiscovered(true);
}
else{
if(matriz[x][y].getNumberOfMinesArround() == 0){
for(int i=min(x);i<max(x);i++)
for(int j=min(y);j<max(y);j++)
discoverWhiteCell(i,j);
}
}
}
There's not a lot of code here but I feel like you're coming at it backwards.
Sorry, I'm not a Java speaker so I'm guessing at some of the syntax. Note that this can go out of bounds--personally, I would add a layer of empty cells around my map so I never need to concern myself with bounds checking.
private void ClickSquare(int x, int y)
{
// Did the user click an already exposed square? If so, ignore
if (matriz[x][y].getDiscovered()) return;
matriz[x][y].SetDiscovered(true);
if (matriz[x][y].getNumberOfMinesAround != 0) return;
// If empty, click all the neighbors
for (int xloop = x - 1; xloop <= x + 1; xloop++)
for (int yloop = y - 1; yloop <= y + 1; yloop++)
ClickSquare(xloop, yloop);
}
I believe you have the discovered test messed up and your version appears to be able to go into infinite (until the stack overflows) recursion as if the neighbor is also zero it will come back to the original cell. My version stops this recursion by only processing a cell if it hasn't already been processed.

Finding nearest point excluding last point LibGDX Java

I am trying to find a way to get a bunch of points to connect via the ShapeRenderer`s method of line(Vector2 first, Vector2 second). So I will explain then show image and code to help.
There is a List of type Vector2 and I need to find the next closest vertice and then exclude the first point. Here is an image of what I mean. I labeled the iterations of the loop in the image.
1st iteration.) it finds the closest point.
2nd iteration.) it sees that the first point is closer but still chooses the third point. This is the core problem, I need to make sure the second point finds the third point even though the first point is the closer one.
Here is the code I have tried to do this.
private void cleanVertices(Array<Vector2> verts){
newVerts = new Array<Vector2>();
Vector2 tmpKey, tmpClose = null;
tmpKey = verts.get(0);
for(int i = 0; i < verts.size; i++){
for(int k = 0; k < (verts.size - 1); k++){
if(k == i)
continue;
//Distance formula
double dist = MathFactory.distance(verts.get(i), verts.get(k));
if(MathFactory.distance(verts.get(i), verts.get(k + 1)) < dist){
tmpClose = verts.get(k + 1);
}else
tmpClose = verts.get(i);
}
tmpKey = tmpClose;
newVerts.add(tmpClose);
}
}'
This does not accomplish what I need, instead, it seems to connect points closest on x-axis. I desperately need help with this. Thanks!
Make a deep copy of the input parameter verts (i.e. a new Array containing the same list of references in verts). Then iterate over that, but remove each point after you choose it as the next "nearest" neighbor.
I'm not familiar with the Array class, but an ArrayList would have the correct behavior when you remove an element. At each point only unvisited points would remain in the list.
since your problem is to find the closest vertex to the second vertex,which is the third in your case, without considering the first one. Make the second for loop starts from the position of the first for loop in every iteration ( k = i). Meaning that the second for loop will not consider the first vertex as point to calculate the distance from.

N amount of boxes within boxes being drawn

Here's what I am trying to replicate:
Currently, my code is as follows:
public void boxes() {
setLocation(20,20);
for(int j =0; j < 5; j = j+1) {
setLocation(20+50*j,20+50*j);
for (int i= 0; i<4; i= i+1) {
move(600-(50*j));
turn(90);
}
}
}
and the result is:
PLEASE do not write me any code, I'd highly prefer just a general explanation as to how I can make it so that the boxes being drawn do not end at the same point. I've been trying to figure it out for the past two hours with no luck and what I currently have is so far the best I've gotten. Thank you!
This is based on http://www.greenfoot.org/scenarios/3535
the problem is with the value you pass to the move() function, it should be:
move(600-(50*j*2));
the reason is that the length of each edge of the square should be shorter by twice the offset from the previous square, as it starts offset units deeper and ends offset units sooner (offset=50 in this case).
The j selects a next square.
Ask yourself:
nice to know: end point of drawing is identical with begin point
you start by (50, 50) more inside. How do you come there from the prior end point
the new length to draw is how much smaller

Categories