I've been working on a game with a mix of awt and slick2d (Rendering is done via awt). Anyway, i'm having a problem with collision. Inside of entity class, I have a collision method:
public boolean colidesWithWall(int idx, int idy) {
//if(Level.solid)
wall = new Rectangle(idx, idy, Tile.Size, Tile.Size);
if (this.getBoundingBox() == null) {
return false;
}
return this.getBoundingBox().intersects(wall);
}
Outside of this in my "Core.java" file, I have a for loop iterate the tiles through the colidesWithWall method. I also have an if statement in here so it will only check the tiles that are on the collision layer. (My map has four layers, Background, Collision, Items and Enemies).
for (int i = 0; i < entities.size(); i++) {
Entity me = entities.get(i);
for (int k = 0; k < 100; k++) {
for (int l = 0; l < 100; l++) {
if (Level.getColision(k, l)) {
Entity entity = entities.get(i);
if (entity.colidesWithWall(k, l)) {
entity.collidedWithWall();
frameCounter = 0;
}
}
}
}
}
Well anyway, what happens is, the game always detects a collision going on. Also, the players X&Y coordinates are defined by this:
((int) ((rouge.screenSize.width) / 2 - Tile.Size / 2 + rouge.oX)) / Tile.Size, ((int((rouge.screenSize.height) / 2 - Tile.Size / 2 + rouge.oY))/Tile.size
rouge.oY and rouge.oX are my camera offsets
Tile.Size is the size of my Tiles: 32
Here's a Screenshot of what happens: http://i.imgur.com/zYONBOC.png
The grey tiles and the tree are supposed to be causing collision, where as the brown ones are not.
Here is what I have for my game. I hope it somehow helps you as I'm not sure how I can help with just what you've given.
Getting the player's bounds:
private static Rectangle getPlayerBounds() {
return new Rectangle((int)player.getPositionX(), (int)player.getPositionY(), playerTexture.getImageWidth(), playerTexture.getImageHeight());
}
Getting the entity(in my case enemy)'s bounds:
private static Rectangle getEnemyBounds(Enemy e) {
return new Rectangle(e.getEnemyPosX(), e.getEnemyPosY(), enemyTexture.getImageWidth(), enemyTexture.getImageHeight());
}
then I have my checkCollision():
public static void checkCollisions() {
for(int i = 0; i < getEnemyList().size(); i++) {
Enemy tempEnemy = getEnemyList().get(i);
if (getPlayerBounds().intersects(getEnemyBounds(tempEnemy))) {
getEnemyList().remove(tempEnemy);
}
}
}
and in the end I just call it in my Movement.java:
MovementChecks.checkCollisions();
Related
I am relatively new to java, and I have an idea for a mechanic I want to implement in to my game. However, I have no idea how to go about solving this problem. My snake game works on a basic coordinate system. I want it to be so that when the snake makes a closed loop (a rectangle or square) the game will detect it has made a loop. I have tried writing a method to locate the part of the snake's body that is the most upper-left, and then checking from there, but it seems to not work very well. Here is the method I attempted to write, if It helps at all. Thank you for any help!!
public boolean checkRing()
{
int topLeftX = 5000;
int topLeftY = 5000;
for(int i = bodyParts;i>0;i--)
{
// Finds coordinates of top left box
if(x[i] < topLeftX)
{
topLeftX = x[i];
}
if(y[i] < topLeftY)
{
topLeftY = y[i];
}
}
// Use isBody() method below (not bug tested) to check for rectangle
boolean lineFoundVert = false;
int checkingX = topLeftX;
int checkingY = topLeftY;
int vertCounter = 1;
while(!lineFoundVert)
{
if(isBody(checkingX, checkingY))
{
vertCounter++;
checkingX++;
}
else
lineFoundVert = true;
}
boolean lineFoundHori = false;
checkingX = topLeftX;
checkingY = topLeftY;
int horiCounter = 1;
while(!lineFoundHori)
{
if(isBody(checkingX, checkingY))
{
horiCounter++;
checkingY++;
}
else
lineFoundHori = true;
}
debug1X = topLeftX + 1;
debug1Y = topLeftY + vertCounter;
debug2X = topLeftX + horiCounter;
debug2Y = topLeftY + 1;
if(isBody(topLeftX + 1, topLeftY + vertCounter) && isBody(topLeftX + horiCounter, topLeftY + 1))
{
return true;
}
return false;
}```
Here is an approximate solution:
private boolean isEdgeCoordinate(Coordinate[] bodyparts, int index) {
// for every bodypart check that its neighbours (bodypart one before and
// bodypart one after) dont share X axis and dont share Y axis. As long
// as that is the case it is an edge.
//additionally for the last bodypart you needto check that it has first
// bodypart as a neighbour and check them as neighbours otherwise no
// rectangle to begin with
}
using this method check the amount of edges in your bodyparts array. If the total number of edges == 4 you have got a square/rectangle
I'm trying to optimize my program by getting rid of duplicate searches or just by generally make things optimized throughout my program and I came across a method in which I can't find any "better" solution what so ever and would love to know if anyone could point me in a direction for refineing it.
First off here is my code that I'm trying to optimize:
public Player spaceBattle(Player player1, Player player2) {
ArrayList<Ship> listOfShipsPlayer1 = this.getShipsOfPlayer(player1);
ArrayList<Ship> listOfShipsPlayer2 = this.getShipsOfPlayer(player2);
Random random = new Random();
int player1hits = 0, player2hits = 0, rolledDie;
for (Ship aShip : listOfShipsPlayer1) {
rolledDie = random.nextInt(10) + 1;
if (rolledDie >= aShip.getShipType().getCombatValue()) {
player1hits += 1;
}
}
for (Ship aShip : listOfShipsPlayer2) {
rolledDie = random.nextInt(10) + 1;
if (rolledDie >= aShip.getShipType().getCombatValue()) {
player2hits += 1;
}
}
for (int i = 0; i < player1hits; ++i) {
if (this.getShipsOfPlayer(player2).size() > 0) {
this.listOfShips.remove(listOfShipsPlayer2.get(i));
} else {
break;
}
}
for (int i = 0; i < player2hits; ++i) {
if (this.getShipsOfPlayer(player1).size() > 0) {
this.listOfShips.remove(listOfShipsPlayer1.get(i));
} else {
break;
}
}
As you can see here I run the same algorithm twice in order to check for first Player1 and then Player2 and add update their respective hits. And then for the amount of hits for each player I then remove a ship.
What I would like to know if its possible to change this bit of code to be able to not have the duplicate code for each player but that it automatically can go through player1 first and then player2 in one loop.
Looking forward to hear from you
You can just create methods.
private int hitShips(List<Ship> ships) {
int result = 0;
for (Ship ship : ships) {
rolledDie = random.nextInt(10) + 1;
if (rolledDie >= ship.getShipType().getCombatValue()) {
result++;
}
}
return result;
}
which makes your code
int player1hits = hitShips(listOfShipsPlayer1);
int player2hits = hitShips(listOfShipsPlayer2);
and similar for the removal of the ships from the list.
void removeShips(List<Ship> ships, int remove) {
int removeCount = Math.max(ships.size(), remove);
Iterator<Ship> it = ships.iterator();
for (int i = 0; i < removeCount; i++) {
it.remove();
}
}
with
removeShips(getShipsOfPlayer(player2), player1hits);
removeShips(getShipsOfPlayer(player1), player2hits);
I'm not sure why you always remove ships from the head of the lists, since combat values seems to be a thing, but that's just a side note.
I wouldn't call this "optimization" so much, but the removal of duplicate code is always good.
You could optimize removeShips as:
void removeShips(List<Ship> ships, int numHits) {
int numToRemove = Math.min(ships.size(), numHits);
if (numToRemove > 0) {
ships.subList(0, numToRemove).clear();
}
}
This method call will result in only one System.arraycopy call, which will shift all remaining elements to the left.
https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#subList-int-int-
I got a project in my Java class which I'm having trouble with.
The project is basically marking coordinates on the screen, making a (complex) polynomial out of them, then solving the polynomial with Newton's method using random guesses and drawing the path of the guesses on the screen.
I don't have a problem with any of the drawing, marking, etc.
But for some reason, my Newton's method algorithm randomly misses roots. Sometimes it hits none of them, sometimes it misses one or two. I've been changing stuff up for hours now but I couldn't really come up with a solution.
When a root is missed, usually the value I get in the array is either converging to infinity or negative infinity (very high numbers)
Any help would be really appreciated.
> // Polynomial evaluation method.
public Complex evalPoly(Complex complexArray[], Complex guess) {
Complex result = new Complex(0, 0);
for (int i = 0; i < complexArray.length; i++) {
result = result.gaussMult(guess).addComplex(complexArray[complexArray.length - i - 1]);
}
return result;
}
> // Polynomial differentation method.
public Complex[] diff(Complex[] comp) {
Complex[] result = new Complex[comp.length - 1];
for (int j = 0; j < result.length; j++) {
result[j] = new Complex(0, 0);
}
for (int i = 0; i < result.length - 1; i++) {
result[i].real = comp[i + 1].real * (i + 1);
result[i].imaginary = comp[i + 1].imaginary * (i + 1);
}
return result;
}
> // Method which eliminates some of the things that I don't want to go into the array
public boolean rootCheck2(Complex[] comps, Complex comp) {
double accLim = 0.01;
if (comp.real == Double.NaN)
return false;
if (comp.real == Double.NEGATIVE_INFINITY || comp.real == Double.POSITIVE_INFINITY)
return false;
if (comp.imaginary == Double.NaN)
return false;
if (comp.imaginary == Double.NEGATIVE_INFINITY || comp.imaginary == Double.POSITIVE_INFINITY)
return false;
for (int i = 0; i < comps.length; i++) {
if (Math.abs(comp.real - comps[i].real) < accLim && Math.abs(comp.imaginary - comps[i].imaginary) < accLim)
return false;
}
return true;
}
> // Method which finds (or attempts) to find all of the roots
public Complex[] addUnique2(Complex[] poly, Bitmap bitmapx, Paint paint, Canvas canvasx) {
Complex[] rootsC = new Complex[poly.length - 1];
int iterCount = 0;
int iteLim = 20000;
for (int i = 0; i < rootsC.length; i++) {
rootsC[i] = new Complex(0, 0);
}
while (iterCount < iteLim && MainActivity.a < rootsC.length) {
double guess = -492 + 984 * rand.nextDouble();
double guess2 = -718 + 1436 * rand.nextDouble();
if (rootCheck2(rootsC, findRoot2(poly, new Complex(guess, guess2), bitmapx, paint, canvasx))) {
rootsC[MainActivity.a] = findRoot2(poly, new Complex(guess, guess2), bitmapx, paint, canvasx);
MainActivity.a = MainActivity.a + 1;
}
iterCount = iterCount + 1;
}
return rootsC;
}
> // Method which finds a single root of the complex polynomial.
public Complex findRoot2(Complex[] comp, Complex guess, Bitmap bitmapx, Paint paint, Canvas canvasx) {
int iterCount = 0;
double accLim = 0.001;
int itLim = 20000;
Complex[] diffedComplex = diff(comp);
while (Math.abs(evalPoly(comp, guess).real) >= accLim && Math.abs(evalPoly(comp, guess).imaginary) >= accLim) {
if (iterCount >= itLim) {
return new Complex(Double.NaN, Double.NaN);
}
if (evalPoly(diffedComplex, guess).real == 0 || evalPoly(diffedComplex, guess).imaginary == 0) {
return new Complex(Double.NaN, Double.NaN);
}
iterCount = iterCount + 1;
guess.real = guess.subtractComplex(evalPoly(comp, guess).divideComplex(evalPoly(diffedComplex, guess))).real;
guess.imaginary = guess.subtractComplex(evalPoly(comp, guess).divideComplex(evalPoly(diffedComplex, guess))).imaginary;
drawCircles((float) guess.real, (float) guess.imaginary, paint, canvasx, bitmapx);
}
return guess;
}
> // Drawing method
void drawCircles(float x, float y, Paint paint, Canvas canvasx, Bitmap bitmapx) {
canvasx.drawCircle(x + 492, shiftBackY(y), 5, paint);
coordPlane.setAdjustViewBounds(false);
coordPlane.setImageBitmap(bitmapx);
}
}
Error 1
The lines
guess.real = guess.subtractComplex(evalPoly(comp, guess).divideComplex(evalPoly(diffedComplex, guess))).real;
guess.imaginary = guess.subtractComplex(evalPoly(comp, guess).divideComplex(evalPoly(diffedComplex, guess))).imaginary;
first introduce a needless complication and second introduce an error that makes it deviate from Newton's method. The guess used in the second line is different from the guess used in the first line since the real part has changed.
Why do you not use, like in the evaluation procedure, the complex assignment in
guess = guess.subtractComplex(evalPoly(comp, guess).divideComplex(evalPoly(diffedComplex, guess)));
Error 2 (Update)
In the computation of the differentiated polynomial, you are missing the highest degree term in
for (int i = 0; i < result.length - 1; i++) {
result[i].real = comp[i + 1].real * (i + 1);
result[i].imaginary = comp[i + 1].imaginary * (i + 1);
It should be either i < result.length or i < comp.length - 1. Using the wrong derivative will of course lead to unpredictable results in the iteration.
On root bounds and initial values
To each polynomial you can assign an outer root bound such as
R = 1+max(abs(c[0:N-1]))/abs(c[N])
Using 3*N points, random or equidistant, on or close to this circle should increase the probability to reach each of the roots.
But the usual way to find all of the roots is to use polynomial deflation, that is, splitting off the linear factors corresponding to the root approximations already found. Then a couple of additional Newton steps using the full polynomial restores maximal accuracy.
Newton fractals
Each root has a basin or domain of attraction with fractal boundaries between the domains. In rebuilding a similar situation to the one used in
I computed a Newton fractal showing that the attraction to two of the roots and ignorance of the other two is a feature of the mathematics behind it, not an error in implementing the Newton method.
Different shades of the same color belong to the domain of the same root where brightness corresponds to the number of steps used to reach the white areas around the roots.
I'm trying to make the game Tetris in java.
I've gotten it to the point where:
a new block is generated when it hits the floor or its y+1 is not null (meaning there's another block under it)
public void collisionCheck(int x, int y) {
if (activetile.getY() == this.height-2 || getTileAt(x, y+1) != null) {
activetile = new Tile(this, 0, 0);
}
}
A row clears when the bottom row is full of non-null values, or the Tetris pieces (for y = 4 (the floor), loop through x till x = 4 and check if all non-null)
public void checkBottomFull(int x, int y) {
while (getTileAt(x,y) != null) {
say("(" + x + ", " + y +")");
if (x == 3) {
say("row is full");
//replace full row with tiles from above
for (int i = 0; i < 4; i++) {
for (int j = 5; j > 0; j--) {
grid[j][i] = getTileAt(i,j-1);
grid[j-1][i] = null;
}
}
break;
}
x++;
}
}
Right now, I'm using keys to move the block:
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_DOWN) {
activetile.setLocation(activetile.getX(), activetile.getY()+1);
System.out.println("coordinates: " + activetile.getX() + ", " + activetile.getY());
collisionCheck(activetile.getX(),activetile.getY());
checkBottomFull(0,4);
repaint();
}
}
There's two issues I'm having:
1) In the picture you'll notice I've dropped the block all the way to the floor... and the row cleared. After it's cleared, it will generate a block to the top left (x=0, y=1) which I have no control over.
2) On the floor there seems to be a red line... which I'm assuming is a row of blocks hidden by the JFrame... I'm not sure why that's there.
FYI: If you're wondering why grid[j][i] has the rows and columns flipped (aka, why it's not grid[i][j]) is because I instantiated it as grid = new Tile[height][width];
Any thoughts?
Thanks!
It is hard to say what is wrong without actually debugging your app.
But maybe try this one:
public void checkBottomFull(int x, int y) {
while (getTileAt(x,y) != null) {
say("(" + x + ", " + y +")");
if (x == 3) {
say("row is full");
//replace full row with tiles from above
for (int i = 0; i < 4; i++) {
for (int j = 4; j >= 0; j--) {
grid[j][i] = getTileAt(i,j-1);
grid[j-1][i] = null;
}
}
break;
}
x++;
}
}
You have 5 rows (indexed from 0 to 4) and 4 columns (indexed from 0 to 3).
What values of height and width do you pass to:
grid = new Tile[height][width];
Because from what I see you should do something like that:
grid = new Tile[5][4];
Bah,
Turns out in the key event, I needed to check if the bottom was full before checking if there is a collision.
I guess what was happening is, when I was checking collisionCheck(activetile.getX(),activetile.getY()); before checkBottomFull(0,4);, when the bottom was full, it would clear the row and set the current row equal to the row above it: grid[j][i] = getTileAt(i,j-1);, the problem was that collisionCheck was generating a new piece and the that newly generated piece was getting cleared and replaced by checkBottomFull.
Putting the collision check after the checkBottomFull ensures that the newly generated piece won't be replaced if bottom is full.
Im working on a falling blocks game in java where you have to move the player around the screen to dodge the blocks. Whenever you get hit by a block, depending on the block type, it will either decrease or increase a int in the player class. Im having the problem that when the player is hit by the block the int keeps going down until the now invisible block is offscreen. Basically I just need a way to check through a object array and when a object meets a specified condition such as (delete == true) it will set the current position of that block in the array to null.
Method for updating the block position:
public void dropFoods(int speed) {
for (int x = 699 - speed; x >= 0; x--) {
for (int y = 0; y < 7; y++) {
if(x > (699 - GUI.HEIGHT) - 10) {
food[y][x] = null;
continue;
}
food[y][x + speed] = food[y][x];
food[y][x] = null;
}
}
}
Method for drawing the blocks (the food are the different types of blocks):
for(int x = 0; x < food.length; x++) {
for(int y = 0; y < food[x].length; y ++) {
Object o = food[x][y];
if(o instanceof Apple) {
new Apple(x * 100, y - Apple.HEIGHT, g);
}
if(o instanceof Burger) {
new Burger(x * 100, y - Burger.HEIGHT, g);
}
}
}
Method for detecting collision with player:
if(Food.getHitBox().intersects(Player.hitBox())) {
willDraw = false;
Player.weight -= 1;
}
You should provide more code and debugging result first.
if(Food.getHitBox().intersects(Player.hitBox())) {
willDraw = false;
Player.weight -= 1;
}
So when something gets hit by player, do you remove the Food object off the map? Because according to this code, you are not.