I really could use some help in order to find a working solution for my game.
My game is almost done, but the walls in my game are still not working as they should.
I have tried to find a solution on the internet for this problem, but i still haven't found a simple way to stop a rectangle just before it will collide with a wall (another rectangle).
Right now i have implemented a collision detection between the player rectangle and the wall rectangle and then stopped it to move, but then it gets stuck inside a wall when it hits.
Want it to stop just before, so it still can move. The code i have done this with so far is here:
Pacman Class
public class Pacman {
private String pacmanup = "pacmanup.png";
private String pacmandown = "pacmandown.png";
private String pacmanleft = "pacmanleft.png";
private String pacmanright = "pacmanright.png";
private int dx;
private int dy;
private int x;
private int y;
private int width;
private int height;
private boolean visible;
private Image imageup;
private Image imagedown;
private Image imageleft;
private Image imageright;
public Pacman() {
ImageIcon i1 = new ImageIcon(this.getClass().getResource(pacmanup));
imageup = i1.getImage();
ImageIcon i2 = new ImageIcon(this.getClass().getResource(pacmandown));
imagedown = i2.getImage();
ImageIcon i3 = new ImageIcon(this.getClass().getResource(pacmanleft));
imageleft = i3.getImage();
ImageIcon i4 = new ImageIcon(this.getClass().getResource(pacmanright));
imageright = i4.getImage();
width = imageup.getWidth(null);
height = imageup.getHeight(null);
visible = true;
x = 270;
y = 189;
}
public int getDx() {
return dx;
}
public void setDx(int dx) {
this.dx = dx;
}
public int getDy() {
return dy;
}
public void setDy(int dy) {
this.dy = dy;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public Image getImageup() {
return imageup;
}
public Image getImagedown() {
return imagedown;
}
public Image getImageleft() {
return imageleft;
}
public Image getImageright() {
return imageright;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public boolean isVisible() {
return visible;
}
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);
}
public void move() {
x += dx;
y += dy;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = -2;
dy = 0;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 2;
dy = 0;
}
if (key == KeyEvent.VK_UP) {
dx = 0;
dy = -2;
}
if (key == KeyEvent.VK_DOWN) {
dx = 0;
dy = 2;
}
}
Here i have created a Rectangle getBounds method which i use to create an rectangle of the pacman and place an image over it.
Barrier class / Wall class
public class Barrier {
private String barrier = "barrier.png";
private int x;
private int y;
private int width;
private int height;
private boolean visible;
private Image image;
public Barrier(int x, int y) {
ImageIcon ii = new ImageIcon(this.getClass().getResource(barrier));
image = ii.getImage();
width = image.getWidth(null);
height = image.getHeight(null);
visible = true;
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public boolean isVisible() {
return visible;
}
public void setVisible(Boolean visible) {
this.visible = visible;
}
public Image getImage() {
return image;
}
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);
}
This class also have the Rectangle getBounds class which i use to detect collision.
The last code i show is how i do the collision detection so far:
Code inside Board class
Rectangle r3 = pacman.getBounds();
for (int j = 0; j<barriers.size(); j++) {
Barrier b = (Barrier) barriers.get(j);
Rectangle r4 = b.getBounds();
if (r3.intersects(r4)) {
System.out.println("Wall hit");
pacman.setDx(0);
pacman.setDy(0);
}
}
Well, what i do, if there is a collision between r3 and r4, i gonna set Dx and Dy to 0.. what i want to find another solution so it detect for collision but i wont get stuck inside a wall, but i don't know how to :/
Hope someone will help.
There are two approaches you can follow. One is ugly but easier, the other one requires a deeper redesign of your classes.
1) Ugly/Simple Approach
In the ugly one, you keep moving your guy before doing the collision checks. Simply move your pacman back to the point where it was not stuck. You accomplish that by inverting the last directions used:
Code inside Board class
Change your reaction in case you find a collision: just walk the same distance, backwards.
if (r3.intersects(r4)) {
System.out.println("Wall hit, move back");
pacman.setDx(-pacman.getDx());
pacman.setDy(-pacman.getDy());
// Possibly need to call move() here again.
pacman.move();
break;
}
Ugly, but should work.
Not recommended to coding perfectionists with OCD and heart disease, though.
2) Redesign
In this approach, you test the position pacman will occupy before doing any actual moves. If that spot is not into any barrier, then perform the movement for real.
Code inside Pacman class
Add this method, so that you can check for collisions against the new bounds.
public Rectangle getOffsetBounds() {
return new Rectangle(x + dx, y + dy, width, height);
}
Code inside Board class
// Strip the call to pacman.move() prior to this point.
Rectangle r3 = pacman.getOffsetBounds(); // Check against the candidate position.
for (int j = 0; j<barriers.size(); j++) {
Barrier b = (Barrier) barriers.get(j);
Rectangle r4 = b.getBounds();
if (r3.intersects(r4)) {
System.out.println("Wall hit");
pacman.setDx(0);
pacman.setDy(0);
// Quit the loop. It's pointless to check other barriers once we hit one.
break;
}
}
// Now we're good to move only in case there's no barrier on our way.
pacman.move();
Particularly I prefer this approach, but it's up to you to pick the best one.
Related
Hi guys so i have this game made where the user avoids aliens coming from the right side of the screen and then they go past the left side. I need the aliens to reappear from the right side once they leave the left side of the screen. How can i go about doing this?
Here is my existing code:
EDIT:
Added alien class underneath main class
PImage background;
int x=0; //global variable background location
Alien alien1;
Alien alien2;
Alien alien3;
Defender user1;
void setup(){
size(800,400);
background = loadImage("spaceBackground.jpg");
background.resize(width,height);
alien1 = new Alien(800,100,5);
alien2 = new Alien(800,200,5);
alien3 = new Alien(800,300,5);
user1 = new Defender(10,height/2);
}
void draw ()
{
drawBackground();
alien1.move();
alien1.render();
alien2.move();
alien2.render();
alien3.move();
alien3.render();
user1.render();
}
void drawBackground()
{
image(background, x, 0); //draw background twice adjacent
image(background, x+background.width, 0);
x -=4;
if(x == -background.width)
x=0; //wrap background
}
void keyPressed()
{
if(key == CODED) {
if (keyCode == UP) {
user1.y = user1.y - 5;
}
else if (keyCode == DOWN)
{
user1.y = user1.y + 5;
}
}
}
final color Alien1 = color(0,255,0);
final color Alien2 = color(50,100,0);
class Alien
{
int x,y;
int speedX, speedY;
Alien(int x, int y, int speedX)
{
this.x = x;
this.y = y;
this.speedX = speedX;
}
void move()
{
x=x-speedX;
float stepY = random(-5,5);
y = y + (int)stepY;
}
//draw an alien
void render()
{
fill(Alien1);
ellipse(x,y,30,30);
fill(Alien2);
ellipse(x,y,50,15);
}
}
If you upload your Alien class then we can give clearer directions but the idea is that your should add the following logic in your move() method.
void move()
{
x=x-speedX;
float stepY = random(-5,5);
y = y + (int)stepY;
if(this.x < 0) {
this.x = 800; // or width, startingPosition, ...
}
}
Edit: Alien class was added so adapted my solution to the code.
I'm creating a space shooter game in Java awt for my college computer science project.
The enemies that I have spawn every 3 seconds via a timer and are added to a LinkedList, and a for loop renders them all.
In the class I have for my player's bullet object, there are if statements to check whether the laser comes into the bounds of an enemy, and if they are all true it removes the enemy from the LinkedList.
However, only the most recent addition to the LinkedList is being removed; the bullet passes through the others and nothing happens. This is my first time making a game, and the first time I've ever used a LinkedList, so excuse any misunderstandings.
The controller class controls the enemies, the Laser class is the bullet and the Enemy class is the Enemy object. There's also a player, Main and GUI class.
import java.awt.*;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
public class Controller
{
private LinkedList<Enemy> e = new LinkedList<Enemy>();
Enemy tempEnemy, tempEnemy2
;
Main main;
int refreshSpawn = 3000; //move timer refresh rate
int xpos;
int width;
int ypos;
int height;
Timer spawnTimer = new Timer();
public Controller(Main main)
{
this.main = main;
spawn();
}
public void spawn()
{
spawnTimer.schedule(new TimerTask()
{
public void run() //run method and timer
{
addEnemy(new Enemy(main, (int)(Math.random()*4+2)));
}
}, 0, refreshSpawn);
}
public void render(Graphics g)
{
for(int i = 0; i < e.size(); i++)
{
tempEnemy = e.get(i);
xpos = tempEnemy.getX();
width = tempEnemy.getXsize();
ypos = tempEnemy.getY();
height = tempEnemy.getYsize();
tempEnemy.render(g);
}
}
public void update()
{
for(int i = 0; i < e.size(); i++)
{
tempEnemy2 = e.get(i);
tempEnemy2.move();
}
}
public void addEnemy(Enemy enemy)
{
e.add(enemy);
System.out.println(e.size());
//spawn();
}
public void removeEnemy()
{
e.remove(tempEnemy);
}
public int getX()
{
return xpos;
}
public int getY()
{
return ypos;
}
public int getXsize()
{
return width;
}
public int getYsize()
{
return height;
}
public Enemy getEnemy()
{
return tempEnemy;
}
}
import java.awt.*;
public class Enemy
{
Image ship; //image of enemy ship
int x, y; //ship position
int speed;
public Enemy(Main main, int speed) //constructing enemy
{
this.speed = speed;
ship = main.getImage(main.getDocumentBase(), "enemyShip"+(int)(Math.random()*6+1)+".png"); //picture for enemy ship
x = (int)(Math.random()*900+1); //enemy has a starting position at a random x point
y = -100; //start ship slightly off screen so it doesn't suddenly appear
}
public void move()
{
y += speed;
if(y > 600)
{
y = -100;
x = (int)(Math.random()*900);
}
}
public void render(Graphics g)
{
g.drawImage(ship, x, y, null);
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public int getXsize()
{
return ship.getWidth(null);
}
public int getYsize()
{
return ship.getHeight(null);
}
}
import java.awt.*;
public class Laser
{
Image img; //image of laser
int laserSpeed = 10; //speed of laser
int x, y; //position of laser
int xSize, ySize; //size of laser
Controller cont;
GUI gui;
public Laser(Image img, int x, int y, Controller cont, GUI gui) //constructing laser
{
this.cont = cont;
this.img = img; //setting laser image
this.gui = gui;
xSize = x; //size of laser
ySize = y; //size of laser
}
public void shoot(int x, int y, int shipSize)
{
this.x = x + (shipSize/2) - (xSize/2);
this.y = y;
}
public void move()
{
y -= laserSpeed;
if(x <= cont.getX() + cont.getXsize() && x + xSize >= cont.getX() - cont.getXsize())
{
if(y <= cont.getY() + cont.getYsize() && y > 0)
{
remove();
cont.removeEnemy();
gui.scoreUp(5);
}
}
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public int getXSize()
{
return xSize;
}
public int getYSize()
{
return ySize;
}
public Image getImage()
{
return img;
}
public void remove()
{
y = -ySize;
x = -100;
}
}
From what I can tell, tempEnemy is assigned to the last element in the LinkedList by the render method. This means that when you call removeEnemy it is removing the last rendered object (likely the last object you added).
What you should be doing is telling the Controller which Enemy it should be using, it has absolutely no idea what your intentions are when you call it...
I am making my first game using LibGDX on android.
I have a background which is 288*511, Now in my game, I need to repeat that background and then translate over it. I have made that game for desktop using Slick2D, and had the same problem, just a bit lower than on my LG G2 phone (4.0.4), is there a way to fix this lag or I am doing something wrong?
The problem is that when it's translating, its moving fine and sometimes jumps 1-2 pixels forward or just stuck for 0.5 seconds or so.
This is my class:
public class Background {
private class RepeatedBackground implements GameObject {
private int x;
private int y = 0;
Sprite background;
public RepeatedBackground(int x, Sprite s) {
this.x = x;
this.background = s;
}
#Override
public void render() {
}
public float getPreferedWidth() {
int w = Gdx.graphics.getWidth();
return (float) (w / 1.15);
}
public float getPreferedHeight() {
int h = Gdx.graphics.getHeight();
return (float) (h / 1.15);
}
#Override
public int getX() {
return this.x;
}
#Override
public int getY() {
return this.y;
}
public Sprite getSprite() {
return this.background;
}
}
private int tra = 0;
private long traTime = 0;
private List<RepeatedBackground> backgrounds = new ArrayList<RepeatedBackground>();
private Level level;
private SpriteBatch backgroundRenderer;
public Background(Level level) {
this.level = level;
this.backgroundRenderer = new SpriteBatch();
}
public void generateBackgrounds() {
int x = 0;
Sprite background = this.level.getFactory().createBackgroundSprite();
for (int i = 0; i < LevelConfig.MAX_BACKGROUND_REPEATS; i++) {
this.backgrounds.add(new RepeatedBackground(x, background));
x += background.getWidth();
}
}
public void render() {
this.backgroundRenderer.getTransformMatrix().translate(-6, 0, 0);
this.backgroundRenderer.begin();
this.backgroundRenderer.setProjectionMatrix(this.level.getInstance().getCamera().combined);
Iterator<RepeatedBackground> itr = this.backgrounds.iterator();
while (itr.hasNext()) {
RepeatedBackground b = itr.next();
Sprite s = b.getSprite();
if (b.getX() - b.getPreferedHeight() < this.level.getInstance().getCamera().viewportWidth) { // this doesn't work properly, but it doesn't load all backgorunds at once but still lags..
this.backgroundRenderer.draw(s, b.getX(), b.getY(), b.getPreferedWidth(), b.getPreferedHeight());
}
}
this.backgroundRenderer.end();
}
}
My create values for camera:
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera(w,h);
camera.setToOrtho(false);
batch = new SpriteBatch();
Texture.setEnforcePotImages(false);
You can use ParallaxBackground class from here
http://www.badlogicgames.com/forum/viewtopic.php?f=17&t=1795
It doesn't depends on the size of the image or camera. It just translates your background continuously
source: http://code.google.com/p/libgdx-users/wiki/ParallaxBackgound
in this class that i have extending JLabel I need to be able to use the mouse to left click, then drag down and/or right to create a rectangle and be able to repeat that process to draw multiple rectangles without losing any of the previous ones and drawing boxes for overlap as well as being able to find the rectangle made by the union of all rectangles like this
my current code was adapted as much as i could from the java demo on Performing Custom Painting the program seems to be behaving in odd ways because of how the repaint method is used to update the JLabel but i have no idea how to fix it
JLabel class
import javax.swing.*;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class JLabelx extends JLabel {
private int squareX = 0;
private int squareY = 0;
private int squareW = 0;
private int squareH = 0;
public JLabelx() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
squareX = e.getX();
squareY = e.getY();
//set coordinates of next rectangle
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
newDraw(e.getX(),e.getY());
//find length and width of next rectangle
}
});
}
protected void newDraw(int x, int y) {
int OFFSET = 1;
if ((squareX!=x) || (squareY!=y)) {
// repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
squareW=x-squareX;
squareH=y-squareY;
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
}
}
protected void paintComponent(Graphics g) {
super.paintComponents(g);
g.setColor(Color.GREEN);
g.fillRect(squareX,squareY,squareW,squareH);
g.setColor(Color.BLACK);
g.drawRect(squareX,squareY,squareW,squareH);
}
}
I have also been given a Rectangle class that looks similar to java.awt.Rectangle which has methods that find the rectangles made by overlaps and the rectangles made by the union of all rectangles, but I don't know how to create rectangle objects with mouse movements and then paint them in this JLabel
public class Rectangle {
private int x,y,width,height;
public Rectangle(int x,int y,int width,int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public Rectangle(Rectangle a)
{
this.x = a.x;
this.y = a.y;
this.width = a.width;
this.height = a.height;
}
public String toString()
{
return "Start: ("+x+","+y+"), Width: "+width+", Height: "+height+"\n";
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public int getWidth()
{
return width;
}
public int getHeight()
{
return height;
}
public void setX(int x)
{
this.x = x;
}
public void setY(int y)
{
this.y = y;
}
public void setWidth(int width)
{
this.width = width;
}
public void setHeight(int height)
{
this.height = height;
}
public int area()
{
return width*height;
}
public boolean overlaps(Rectangle a)
{
if ((x>a.x+a.width) || (a.x>x+width) || (y>a.y+a.height) || (a.y>y+height))
{
return false;
}
return true;
}
public Rectangle intersect(Rectangle a)
{
if (!overlaps(a))
return null;
int left,right,top,bottom;
if (x<a.x)
left = a.x;
else
left = x;
if (y<a.y)
bottom = a.y;
else
bottom = y;
if ((x+width)<(a.x+a.width))
right = x+width;
else
right = a.x+a.width;
if ((y+height)<(a.y+a.height))
top = y+height;
else
top = a.y+a.height;
return new Rectangle(left,bottom,right-left,top-bottom);
}
public Rectangle union(Rectangle a)
{
int left,right,top,bottom;
if (x<a.x)
left = x;
else
left = a.x;
if (y<a.y)
bottom = y;
else
bottom = a.y;
if ((x+width)<(a.x+a.width))
right = a.x+a.width;
else
right = x+width;
if ((y+height)<(a.y+a.height))
top = a.y+a.height;
else
top = y+height;
return new Rectangle(left,bottom,right-left,top-bottom);
}
}
Not sure why you are extending a JLabel to do custom painting. The tutorial showed you how to use a JPanel.
For the two common ways to do incremental paint, check out Custom Painting Approaches:
Use a List to keep track of the Rectangles (this is probably what you want since you want to be able to test for intersections.
Use a BufferedImage.
I have a problem with my code here. I want to make a game with thow ball on each side of screen, on ball being controlled by the user and the other one by the computer. Both ball shoot to each other, and if the bullets intersects one with another, i need to make something happen. I managed to do some thing here, and I have two class, one for the player bullets, and the other one for the enemies bullets, and the bullets are created trough arraylists. All works fin until now, but if I try ti make them collision with each other,it doesnt work at all. I've tried a lot of things but none of it worked, and I would really appreciate if someone could help me.
That is the Player Projectile class:
import java.awt.Rectangle;
public class Projectiles {
private int x, y, speedX;
private boolean visible;
private int width = 10;
private int height = 10;
private Rectangle r;
public Projectiles(){
}
public Projectiles(int startX, int startY) {
x = startX;
y = startY;
speedX = 1;
visible = true;
r = new Rectangle(0, 0, 0, 0);
}
public void update(){
x += speedX;
r.setBounds(x, y, width, height);
if (x > 800){
visible = false;
r = null;
}
if (x < 800){
checkCollision();
}
}
private void checkCollision() {
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeedX() {
return speedX;
}
public boolean isVisible() {
return visible;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public Rectangle getR() {
return r;
}
public void setR(Rectangle r) {
this.r = r;
}
}
And this one is the Enemy_Projectile class:
import java.awt.Rectangle;
public class Enemy_Projectiles {
private int x, y, speedX;
private boolean visible;
private int width = 30;
private int height = 20;
public static Rectangle r;
Projectiles p1;
public Enemy_Projectiles(int startX, int startY) {
x = startX;
y = startY;
speedX = 1;
visible = true;
r = new Rectangle(0, 0, 0, 0);
}
public void update() {
x -= speedX;
r.setBounds(x, y, width, height);
if (x < 0) {
visible = false;
r = null;
}
if (x > 0){
checkCollision();
}
}
private void checkCollision() {
if(r.intersects(p1.getR())){
visible = false;
System.out.println("Coliziune!!");
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeedX() {
return speedX;
}
public boolean isVisible() {
return visible;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
}
Do not check intersection after the frame has been drawn. Let's say you have a slow computer and your bullets intersect, but they have moved out of intersection in one frame.
You need to apply high school physics/geometry. Calculate where the bullet will be well before you render it. Then, calculate where the ball will be, and construct a line segment for each from where they are now, to where they will be on the next frame. Check if these segments intersect. Then you will have a fool-proof method of checking for intersection.
This method is similar to how physics and intersections between objects are handled inside of a game engine like Unity.