I have been working on android apps for a long time but now I have decided to create a game aside with my pre-calculus final. I have completed the whole code and it works perfectly except one tiny issue. First of the game is based on flying pig(my classmate's face) avoiding top and bottom osticle. I developed an algorithm so that the obsticles are evenly spaced and based on random selection placed either as the top or bottom of the screen but never both at the same time!. The algorithm that needs improvement is in the 3rd code segment!
This is the screenshot of the problem: screenshot here
(My account is new so stackoverflow wont let me to share photos directly)
This is the class that calls updates for all dynamic objects (ship = pig, bacon = bonus item, BM = BarrierManager class's update() which updates the obsticles)
//this will update the resources
void Update(float dt) {
ship.update(dt);
//bumbing
if (!ship.death) {
background.update(dt);
**BM.update(dt);**
for (int i = 0; i % 5 == 0; i++) {
bacon.update(dt, BM.position);
}
}
ArrayList<Point> bacon_point = new ArrayList<Point>(bacon.getArray());
if (ship.bump(bacon_point.get(0), bacon_point.get(1), bacon_point.get(2), bacon_point.get(3))) {
bacon.setX(-200);
bacon.setY(-200);
Message msg = BM.game_panel.game.handler.obtainMessage();
msg.what = 0;
BM.game_panel.game.handler.sendMessage(msg);
}
for (int i = 0; i < BM.TopWalls.size(); i++) {
ArrayList<Point> temp = new ArrayList<Point>(BM.TopWalls.get(i).getArray());
//after we have accest the TopWalls arraylist we can call bump that check TopWalls object's points position with the pig's points
ArrayList<Point> temp2 = new ArrayList<Point>(BM.BottomWalls.get(i).getArray());
//after we have accest the TopWalls arraylist we can call bump that check BottomWalls object's points position with the pig's points
if ((ship.bump(temp.get(0), temp.get(1), temp.get(2), temp.get(3))) || (ship.bump(temp2.get(0), temp2.get(1), temp2.get(2), temp2.get(3))) || ship.death) {
ship.death = true;
game.onStop();
while(f==0) {
MediaPlayer mp = MediaPlayer.create(game, R.raw.explosion_fart);
mp.start();
f++;
}
f++;
Message msg = BM.game_panel.game.handler.obtainMessage();
msg.what = 1;
BM.game_panel.game.handler.sendMessage(msg);
i = BM.TopWalls.size()-1;
if(f == 8){
thread.setRunning(false);
}
}
}
}
In the BarrierManager I have created this update method which takes float dt = MainTheards general time for the game.
TopWalls is ArrayList this ArrayList is composed of top obsticles. Bottom walls is the same but BottomWalls.
//zreb decides if it should create TopWalls or BottomWalls object. This parameter is later transfered to the Barier.update method where I work with it
public void update(float dt){
for (int i=0;i<Num+1; i++) {
int zreb = new Random().nextInt(2);
//{if} to make the spacing bigger
if (i % 5 == 0){
**TopWalls.get(i).update(dt, true, zreb);
BottomWalls.get(i).update(dt, false, zreb);**
if(zreb == 0){
position.set(TopWalls.get(i).getX(), TopWalls.get(i).getY());
}
else{
position.set(BottomWalls.get(i).getX(),BottomWalls.get(i).getY());
}
}
}
}
Now this algoritm in the Barrier.class is where the magic went wrong. This update method takes the float dt mentioned earlier, a boolean variable for determining if the obsticle we work with at that instance is the Top or Bottom, and the zreb random int that determines if the top or bottom obsticle is going to be shown.
//problem! needs to be discussed
public void update(float dt, boolean b, int zreb) {
//checking if the barrier is still there
if (x<-bitmap.getWidth()){
//'b'is passed from the Barriermanager - 'update' method, determining if we have to use monkey-true or farmer-false
int raz = 200;
int vyska = BM.dpos;
//'zreb' helps me to randomly determine if monkey or ballard is going to appear
//here it determines if we are going to have Top or Bottom obsticle in the game
if(zreb == 1) {
vyska = BM.dpos - raz;
}
else {
vyska = BM.dpos + raz;
}
//koniec tohto trienedia
if (b)
{
//setting the y value for the top wall
y = vyska - BM.dl/2 - bitmap.getHeight()/2;
}
else{
//setting the y value for bottom wall
y = vyska + BM.dl/2 + bitmap.getHeight()/2;
}
//setting x-value
x = (int) (x +bitmap.getWidth()*(BM.TopWalls.size()-1));
}
x = (int) (x - BM.game_panel.ShipSpeed*dt);
}
Do you have any idea why this "one-or-the-other" condition is not working properly?
This would help me lot because this error made me deactivate the app from the store.
Related
I am simply trying to make a generic way to check for collision between rectangles. If you hit the top of a rectangle stop moving. However my rectangles seem to stop regardless of the x coordinate. I have three rectangles falling and one static rectangle that doesn't move, they are supposed to all fall on top of this static rectangle however when I run the code this happens.
Here is the collision handler code
float distanceY, furthestLeft;
public void update() {
for (int i = 0; i < stageObjects.size(); i++) {
iPos = stageObjects.get(i).getPosition();
iDim = stageObjects.get(i).getDimensions();
for(int k = 0; k < stageObjects.size(); k++){
kPos = stageObjects.get(k).getPosition();
kDim = stageObjects.get(k).getDimensions();
if(k == i){
continue;
}
distanceY = assignDy();
furthestLeft = assignDx();
//DistanceY is the subtraction of one objects y coordinate and
// if it equals 0 then they are colliding and the furthest left
// is the bottom right x coord of the furthest left objects x
//coord so it should check if this x is contained within an
// objects left x coord to right x coord
if(distanceY <= 1 && distanceY >= 0 && furthestLeft >= iPos.x && furthestLeft <= iPos.x + iDim.x){
stageObjects.get(i).react(Tuples.HIT_BOTTOM);
stageObjects.get(k).react(Tuples.HIT_FROM_TOP);
System.out.println("Collision: " + stageObjects.get(i).toString() + " with " +
stageObjects.get(k).toString());
}
}
}
}
}
public float assignDy(){
if(kPos.y > iPos.y){
return Math.abs(kPos.y - (iPos.y + iDim.y));
}else
return Math.abs(iPos.y - (kPos.y + kDim.y));
}
public float assignDx(){
if(kPos.x > iPos.x){
return kPos.x + kDim.x;
}else
return iPos.x + iDim.x;
}
The error lies here and here is the react method
public void react(int occurence){
if(occurence == Tuples.HIT_BOTTOM){
velocity.y = 0;
}
}
However, if they are further apart the code works perfectly look.
I have also noticed that the rectangle can fall through other rectangles if it is to the left of another rectangle, but if it further to the right at all it will get hung as if it landed on the rectangle. The only reason the above image worked is because the furthest right fell first, anything to the left to another rectangle will get hung as well if it falls after the rectangle to the left
I just don't see what exactly I am doing wrong any help is greatly appreciated!
Change iPos in the condition to something more generic, assign a variable like assignDx and dy to ccheck if Ipos or kPos is what you need to check for like so
public void assignOx(Vector2 ox){
if(kPos.x > iPos.x){
ox.x = iPos.x;
ox.y = iPos.x + iDim.x;
}else{
ox.x = kPos.x;
ox.y = kPos.x + kDim.x;
}
}
I'm making a game engine, and I want to have a rope object in the game. I've created the rope, and it behaves perfectly, except that if I apply a force to the bottom of the rope (like attaching the player to the rope and moving the player), the force doesn't propagate to the rest of the rope.
This is what the rope looks like, even when I try to move the player:
I would like the rope to move along with the player, but keep the player attached to the bottom of the rope.
This is the update method from the Rope class
public void update() {
for (int i = 0; i < segments.size(); i++) {
RopeSegment previous = null;
if (i != 0) {
previous = segments.get(i - 1);
}
final RopeSegment seg = segments.get(i);
// do collision detection
seg.update();
// if we are not the first (position locked) segment
if (previous != null) {
// if we are out of range of the previous segment
if (seg.getCenter().toPoint().distanceSq(previous.getCenter().toPoint()) > MAX_DIST * MAX_DIST) {
// pull us back in
final Vec2D previousCenter = previous.getPosition();
seg.applyForce(previousCenter.subtract(seg.getPosition()).multiply(0.01));
seg.setPosition(previousCenter.add(seg.getPosition().subtract(previousCenter).unit()
.multiply(MAX_DIST)));
}
}
}
// lock position of first segment
segments.get(0).setPosition(getLockposition());
segments.get(0).setVelocity(new Vec2D(0, 0));
}
and this is the relevant code from the update method of the Player class
if (rope != null) {
if (rope.getLockposition().toPoint().distanceSq(getCenter().toPoint()) > Rope.MAX_DIST * Rope.MAX_DIST) {
setCenter(rope.getLastSegment().getCenter());
}
}
If I were you: I would find the number of rope segments (Depending on height), there are between the player and the top of the screen (Y : 0px); thereby, allowing you to constantly update an integer; or appropriate size variable, with how many segments to draw. Then, every time you redraw, you can make the rope above the player. This would entitle deleting most of what you have, but I believe it to be a bit more efficient. If you want to make the rope look more 'Rope Like', then you could use an ArrayList, updated every time you go to draw, which will have a class defining position and a Vec2D which holds velocity, which will be used to increase the x position of the rope. e.g.
List<Rope> ropes = new ArrayList<>(); //Fill This With Ropes. . . //First is The Farthest Up!
class Rope {
int x, y;
short velocity;
//Constructor
}
void updateRopes(int playerX) {
for(Rope r : ropes)
r.x += (r.velocity < (playerX - r.x)) ? r.velocity : (playerX - r.x); //You Can Make a Variable Which Holds (playerX - r.x) For Efficiency, or Keep For RAM
}
void playerMove() {
int yDec = ropes.size() / 5; //5 Is the Presumable Speed of The Character. . .
int tempVeloc = 5;
for(int i = 0; i < ropes.size(); i++)
if((i % yDec) == 0 & i != 0) tempVeloc -= 1;
//The Other Player-Move Based Code. . .
}
EDIT:
I believe your problem is that you are not actually editing the classes inside of the array, you are making a constant copy of them; thereby not changing the object because you have not made a pointer to them. . .
What you should do is this:
RopeSegment seg = segments.get(i - 1);
I just started a new 2D game using Java, LWJGL, and Slick Util but I can't seem to figure out a good way to make collision detection.
If I wanted to, it would be easy to detect collision between 2 entities with the Rectangle intersect method, but it can only check the collision with a certain area you specify.
I have thought that I could make a list of every entity and its coordinates as its created and then run the intersect method through the list, but then it would check for collision with every entity on the entire map for every time the game updated and I think that would be too inefficient.
Does anyone know a more efficient way to create collision detection? If there was some way i could check if there was an entity at every point the character moved that would probably be the best.
If I have not enough information or I made this sound too confusing please tell me and I can try to clarify things. Also as a side question, what are the benefits of using slick util or slick 2D over one another. Thanks for the help!
The usual way to solve this is a scene graph, a hierarchical system of the objects of the game world.
You might want to look at this and this.
Shortened: you logically group your objects under nodes and assign the nodes a bounding rectangle that encompasses all its sub-nodes and leaves(objects). Everything is grouped again under one main node to access the tree. Now you can test a object for collision with a node, usually starting from the main node. If you get a hit you check its sub-nodes and leaves.
This will take some time to implement but can cut down on CPU usage if the tree structure/grouping is done right. It has also the benefit that you can implement local transforms which makes moving objects relative to each other easier.
Because I hate "The usual way", I made an array of all the coordinates and then checked if a single point hit the coordinate.
Here is a slight modification of my code to demonstrate (It is in 3D):
for (CannonBall can : GameServer.ballss){ //Go through all cannonballs
if (can.owner != cl){ //Can.owner is the ship, cl is the player the cannonball is being checked with to see if colliding.
int distancex = (int) (can.x - cl.z);
int distancez = (int) (can.z - cl.x);
final int distancey = (int) (can.y - cl.y);
double xRot = Math.cos(Math.toRadians(cl.rotation)) * (distancex - 0) - Math.sin(Math.toRadians(cl.rotation)) * (distancez - 0) + 0;
double zRot = Math.sin(Math.toRadians(cl.rotation)) * (distancex - 0) - Math.cos(Math.toRadians(cl.rotation)) * (distancez - 0) + 0;
distancex = (int) xRot;
distancez = (int) zRot;
try{
if (true){ //Skip different coordinates for different ships for demonstration purposes
i = GameServer.coords[GameServer.DELTA + distancex][GameServer.DELTA + distancez][GameServer.DELTA + (distancey)];
}
if (i == 1){
if (can.owner != cl){
remcan.add(can);
if (can.type == 0){
double damage = (100 + Math.random()*25);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}
if (can.type == 1){
double damage = (Math.random() * 500);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}else{
double damage = (100 + Math.random()*25);
if (cl.type == 1){
damage/=2;
}
if (cl.type == 2){
damage*=2;
}
cl.damage-=damage;
}
crash = true;
if (cl.damage < 1){
if (!cl.sinking){
cl.sinking = true;
}
}
}
}
}catch (Exception e){
e.printStackTrace();
}
}
GameServer.coords is an int[][][], which is given coordinates like so:
public static int[][][] coords;
public void CollisionSetup(){
try{
File f = new File("res/coords.txt");
String coords = readTextFile(f.getAbsolutePath());
for (int i = 0; i < coords.length();){
int i1 = i;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String x = coords.substring(i, i1).replace(",", "");
i = i1;
i1 = i + 1;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String y = coords.substring(i, i1).replace(",", "");;
i = i1;
i1 = i + 1;
for (; i1 < coords.length(); i1++){
if (String.valueOf(coords.charAt(i1)).contains(",")){
break;
}
}
String z = coords.substring(i, i1).replace(",", "");;
i = i1 + 1;
//buildx.append(String.valueOf(coords.charAt(i)));
////System.out.println(x);
////System.out.println(y);
////System.out.println(z);
//x = String.valueOf((int)Double.parseDouble(x));
//y = String.valueOf((int)Double.parseDouble(y));
//z = String.valueOf((int)Double.parseDouble(z));
double sx = Double.valueOf(x);
double sy = Double.valueOf(y);
double sz = Double.valueOf(z);
javax.vecmath.Vector3f cor = new javax.vecmath.Vector3f(Float.parseFloat(x), Float.parseFloat(y), Float.parseFloat(z));
//if (!arr.contains(cor)){
if (cor.y > 0)
arr.add(new javax.vecmath.Vector3f(cor));
if (!ship.contains(new Vector3f((int) sx, (int) sy, (int) sz)))
ship.add(new Vector3f((int) sx, (int) sy, (int) sz));
Float.parseFloat(z)));
}
}
public void setUpPhysics() {
//coords = new int[20][20];
coords = new int[80][80][80];
coords1 = new int[80][80];
//coords[-5 + DELTA][7 + DELTA] = 11;
for (javax.vecmath.Vector3f vec : arr){
coords[DELTA+(int) vec.x][DELTA+(int) vec.z][DELTA + (int) vec.y] = 1; //This is line 124
coords1[DELTA+(int) vec.x][DELTA+(int) vec.z] = 1;
}
}
Though it has limitations on collision interaction, it works for cannonballs colliding with a ship and checking the front of a ship to see if it has hit another ship. Also, it uses barely any CPU.
No idea on the opinions of other programmers on such a method.
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 8 years ago.
I have these classes which is the 3rd and 4th child of a base class in my game:
/*
* List of player states:
* * normal * explode */
public class LocalPlayer extends MovingObjects{
//minus 1 laps to start to accommodate going over the start line for the first time
public int lapsCompleted = -1;
public LocalPlayer(int localPlayerNumber) {
/*
* This line below and the variable localPlayerNumber will not be needed or will be different
* if later on decide to do custom rocket designs - not needed for this stage but bear in mind if the decision is
* made to go down that road this and the game object will have to be reconsidered as early as possible.
*/
super(16, "assets/images/player" + localPlayerNumber , ".jpg", new Vector(373, 450 + (55 * localPlayerNumber)));
}
//basic constructor just initialises MovingObjects Variables to zero values
public LocalPlayer(){
super();
}
///// Uploading Position Methods
public void update(){
if(objectState == "explode"){
}
if(objectState == "normal"){
super.update();
//look for edge of map and stop player leaving and reduce speed to 0
if(position.x > rightEdge - icon.getIconWidth()){
position.x = rightEdge - icon.getIconWidth();
speed = 0;
}else{
if(position.x < leftEdge){
position.x = leftEdge;
speed = 0;
}
}
if(position.y > downEdge - icon.getIconHeight()){
position.y = downEdge - icon.getIconHeight();
speed = 0;
}else{
if(position.y < upEdge){
position.y = upEdge;
speed = 0;
}
}
}
}
///// Movement Methods
//Increases speed
public void up(){
if(speed == 0){
speed = 2;// 2 is minimum speed to achieve all driving angles
}else
if(speed < 11){
speed++;
}
}
//Decreases speed
public void down(){
if(speed > 2){
speed--;
}else{
speed = 0;
}
}
//Turns image and angle 22.5 degrees to the right
public void right(){
if(angle == 337.5)
{
angle = 0;
imageNumber = 0;
}else{
angle = angle + 22.5;
imageNumber = imageNumber + 1;
}
}
//Turns image and angle 22.5 degrees to the left
public void left(){
if(angle == 0)
{
angle = 337.5;
imageNumber = 15;
}else{
angle = angle - 22.5;
imageNumber = imageNumber - 1;
}
}
// works out start grid currently only vertical lines
//add more levels either start all the same way or needs updating
public Vector getStartPos(int serverNumber, CheckPoints line)
{
int row ;
Vector vReturn;
if (serverNumber % 2 == 0) {
// even
row = serverNumber/2;
//this needs some explaining:
//vectorX = row * width of image * gap to next player
//vectorY = getline y and inset slightly(will see how goes)
vReturn = new Vector((line.pos1.x + 10 ) - row * (50 + 10), line.pos1.y + 5);
} else {
// odd
row = (serverNumber + 1)/2;
vReturn = new Vector((line.pos2.x +10) - row * (50 + 10), line.pos2.y - 55);
}
return vReturn;
}
}
and:
import java.awt.image.BufferedImage;
public class NetworkedLocalPlayer extends LocalPlayer{
RocketSpecificServer server = new RocketSpecificServer();
public NetworkedLocalPlayer(String ipAddress,int numOfImages,String filePre, String fileE, CheckPoints finishLine) {
//sign player into server
server.setUpNetwork(ipAddress);
LoadContent.gameSettings = (GameSettings) server.signIn();
//get server number (needed for initialising)
serverNumber = Integer.parseInt(((StringReturnSerial)server.getServerNumber()).s);
//this is temp and should be changed later!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//filePre = filePre + serverNumber;
filePre = filePre + 1;
//Initialise image variables
imageVariables(numOfImages,filePre,fileE);
//work out pos
position = getStartPos(serverNumber,finishLine);
//get images
initImageArray();
}
public void update(){
//updates players info table checks the state of this object
//hasn't been changed by another player
LoadContent.serverPlayerInfo =(PlayerPositionsSerial) server.getPos();
objectState = LoadContent.serverPlayerInfo.playersArray[serverNumber][4];
//usual update
super.update();
//updates server
LoadContent.serverPlayerInfo = (PlayerPositionsSerial) server.updatePos(angle, position.x, position.y,objectState);
}
}
The problem is the update method. In the NetworkedLocalPLayer player class it asks the server for a serialised class which holds all the players positions in the game (and someother bits) that is assigned to the static version in LoadContent class which implements my gameloop. the update method then checks its own position in the playertable array to update its own objectState variable which I can see when using breakpoints comes back as its supposed to as "normal". It then call the parents update method which starts executing and will stop on line in the LocalPlayer class :
if(objectState == "normal"){
the next line is :
super.update();
which should call the super update method of the MovingObjects class which i can also provide if you think it will help but bassically the I have a break opint inside the MovingObjects class and on the super.update() call in the LocalPlayer class which never get hit.
When i change a variable in the game loop to turn multiplayer off which has nothing to do with this but directly used the localPlayer class as it is this method fire perfectly fine and has done unchanged for ages. So is there a reason I cant use super like this? im now getting any errors or exceptions
Thank you
for any help John harris
Never compare Strings with ==. Do it like this (assuming objectState cannot be null - otherwise you could write "explode".equals(objectState) but I find it harder to read):
public void update(){
if(objectState.equals("explode")){
}
if(objectState.equals("normal")){
super.update();
// ...
}
}
If using Java 7, you can also switch on Strings (have a look at the changes introduced with Java 7).
You problem is that objectState == "normal" is always false.
Use "normal".equals(objectState) instead
So I am making a snake game, but if I move from one direction to the other really fast then it says I made a collision with the body and ends the game (for example, if I am going left and I hit down and then left again really fast or down and right really fast, etc.)
I've tried a few things already. I changed the way that it checked for a collision by making it a .intersects rather than checking if (x == body[i][0] && y = body[i][1]). I also did a few System.out.println()'s to see if maybe something was going wrong there. I noticed that sometimes one of the values repeats (either x or y depending on the direction), but I can't figure out why... I figure that the repeating is why it messes up the collision, but I can't find the spot where it would be making it repeat.
x and y are being changed by a thread.
Here is the "Drawing" portion of my code. If you need any other snippets of code please let me know.
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (numOfFood == 1) {//Checks wether there is food on the GUI
g.setColor(Color.BLUE);
g.fillRect(foodX,foodY,12,12);
}
else {
foodX = random.nextInt(103)*12; //Both this and the below line get a random x or y value to put on GUI for food placement
foodY = random.nextInt(57)*12;
numOfFood = 1;
}
Rectangle headRect = new Rectangle( x, y, 12, 12 ); //Actual rectangle of the head
Rectangle foodRect = new Rectangle(foodX, foodY, 12, 12); //Food rectangle
g.setColor(Color.RED);
g.fillRect(x,y,12,12); //Draws head of Snake
g.setColor(Color.WHITE);
g.fillRect(x+2,y+2,8,8); //Draws a white square in the head of the snake
for (int i = 0; i < n; ++i) { //Collision Checker
Rectangle bodyRect = new Rectangle(body[i][0],body[i][1],12,12);
if ( headRect.intersects(bodyRect)) {
for (int j = 0; j < n; ++j) {
body[j][0] = -1;
body[j][1] = -1;
}
numOfFood = 1;
n = 0;
x = 624;
y = 348;
endGame = true;
}
}
g.setColor(Color.RED);
if (n > 0) { //Puts the snakes body behind the head
for (int i = 0;i < n; ++i) {
g.fillRect(body[i][0],body[i][1],12,12);
}
}
for (int i = n-1;i >= 0; --i) { //Inserts the head at the first part of the array so that the body moves
if (body[i][0] != -1 && body[i][1] != -1) {
body[i+1][0] = body[i][0];
body[i+1][1] = body[i][1];
}
if (i == 0) {
body[i][0] = x;
body[i][1] = y;
}
}
if (headRect.intersects(foodRect)) { //If the food rectangle and the head rectangle intersect then the snake got the food.
numOfFood = 0;
n++;
}
}
When do you call paintComponent? I suspect that you have one method that continuously moves the snake forward in regular intervals, but paintComponent is responsible for making the snake longer.
You should move collision and moving the snake into the same method that is responsible for moving the head in the direction the snake is moving.
Otherwise, paintComponent might be called many times on one move update, and this is responsible for duplicates of x and y in your array.