Collisions mit festen Objekten

Mr. Moon

Mitglied
Hallo, ich baue zur Zeit einen Bombermanklon und orientiere mich an http://archon.bplaced.net/bain09/Studium/Programmieren/Java/Turorials/Spiele/Tutorial%20f%FCr%20Java-Spiele%20.pdf

Ich bin zuzeit am Grübeln, wie ich es mache, dass man durch bestimmte Objekte nicht hindurch gehen kann. Ich habe die Kollisionserkennungsmethoden aus dem Tutorial übernommen und bin am überlegen, ob ich es damit irgendwie machen kann. Mein Problem ist, dass wenn jetzt bspw. die Spielfigur mit einem Objekt kollidiert müsste ich den horizontalen oder vertikalen Speed der Spielfigur auf Null setzen und die Spielfigur ein paar Pixel weiter nach links,rechts, oben, unten hinsetzen, je nachdem von welcher Seite die Spielfigur mit dem Objekt kollidiert. Da ist auch mein Problem. Wie finde ich heraus von welcher Seite die Spielfigur mit dem Objekt kollidiert. Wenn zum Beispiel die rechte obere Ecke des Spielers mit dem Objekt kollidiert, weiß man ja nicht, ob die Figur nun von unten oder links kam.

Ich bin dankbar für jede Hilfe

Grüße Mr. Moon
 

Mr. Moon

Mitglied
Könnt ihr mir gleich auch nochmal bei diesem Fehler helfen:

Exception in thread "Thread-3" java.awt.image.RasterFormatException: (y + height) is outside of Raster
at sun.awt.image.ByteInterleavedRaster.createWritableChild(Unknown Source)
at java.awt.image.BufferedImage.getSubimage(Unknown Source)
at Sprite.checkOpaqueColorCollisions(Sprite.java:68)
at Block.collidedWith(Block.java:12)
at GamePanel.doLogic(GamePanel.java:154)
at GamePanel.run(GamePanel.java:203)
at java.lang.Thread.run(Unknown Source)

Java:
import  java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

public abstract class Sprite extends Rectangle2D.Double implements Drawable, Movable {

	long delay;
	long animation = 0;
	protected double dx;
	protected double dy;
	GamePanel parent;
	BufferedImage[] pics;
	int currentpic = 0;
	boolean remove = false;
	int loop_from;
	int loop_to;
	
	public Sprite(BufferedImage[] i, double x, double y, long delay, GamePanel p) {
		pics        = i;
		this.x      = x;
		this.y      = y;
		this.delay  = delay;
		this.width  = pics[0].getWidth();
		this.height = pics[0].getHeight();
		parent      = p;
		loop_from   = 0;
		loop_to     = pics.length - 1;
	}
	
	public void setX(double i) {
		x = i;
	}
	
	public void setY(double i) {
		y = i;
	}
	
	public void setVerticalSpeed(double d) {
		dy = d;
	}
	
	public void setHorizontalSpeed(double d) {
		dx = d;
	}
	
	public double getVerticalSpeed() {
		return dy;
	}
	
	public double getHorizontalSpeed() {
		return dx;
	}
	
	public abstract boolean collidedWith(Sprite s);
	
	public boolean checkOpaqueColorCollisions(Sprite s) {
		
		Rectangle2D.Double cut = (Double) this.createIntersection(s);
		
		if((cut.width < 1) || (cut.height < 1)) {
			return false;
		}
		
		Rectangle2D.Double sub_me  = getSubRec(this, cut);
		Rectangle2D.Double sub_him = getSubRec(s, cut);
		
		BufferedImage img_me = pics[currentpic].getSubimage((int) sub_me.x, (int) sub_me.y, (int) sub_me.width, (int) sub_me.height);
		BufferedImage img_him = pics[currentpic].getSubimage((int) sub_him.x, (int) sub_him.y, (int) sub_him.width, (int) sub_him.height);
		
		for(int i = 0; i < img_me.getWidth(); i++) {
			for(int n = 0; n < img_him.getHeight(); n++) {
				
				int rgb1 = img_me.getRGB(i, n);
				int rgb2 = img_him.getRGB(i, n);
				
				if(isOpaque(rgb1) && isOpaque(rgb2)) {
					return true;
				}
			}
		}
		
		return false;
	}
	
	protected Rectangle2D.Double getSubRec(Rectangle2D.Double source, Rectangle2D.Double part) {
		
		Rectangle2D.Double sub = new Rectangle2D.Double();
		
		if(source.x > part.x) {
			sub.x = 0;
		}
		
		else {
			sub.x = part.x - source.x;
		}
		
		if(source.y > part.y) {
			sub.y = 0;
		}
		
		else {
			sub.y = part.y - source.y;
		}
		
		sub.width  = part.width;
		sub.height = part.height;
		
		return sub;
	}
	
	protected boolean isOpaque(int rgb) {
		
		int alpha = (rgb >> 24) & 0xff;
		//red   = (rgb >> 16) & 0xff;
		//green   = (rgb >> 8) & 0xff;
		//blue   = (rgb) & 0xff;
		
		if(alpha == 0) {
			return false;
		}
		
		return true;
		
	}
	
	public void drawObjects(Graphics g) {
		g.drawImage(pics[currentpic], (int) x, (int) y, null);
	}
	
	public void doLogic(long delta) {
	
		animation += (delta / 1000000);
		
		if(animation > delay) {
			animation = 0;
			computeAnimation();
		}
		
	}
	
	public void move(long delta) {
		
		if(dx != 0) {
			x += dx * (delta / 1e9);
		}
		
		if(dy != 0) {
			y += dy * (delta / 1e9);
		}
	}
	
	private void computeAnimation() {
		
		currentpic++;
		
		if(currentpic > loop_to) {
			currentpic = loop_from;
		}
	}
	
	public void setLoop(int from, int to) {
		loop_from  = from;
		loop_to    = to;
		currentpic = from;	
	}
}

Java:
import java.awt.image.BufferedImage;


public class Block extends Sprite {
    
	public Block(BufferedImage[] i, double x, double y, long delay, GamePanel p) {
		super(i, x, y, delay, p);
	}
	
	public boolean collidedWith(Sprite s) {
		
		return checkOpaqueColorCollisions(s);
				
	}
}

Java:
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Vector;

public class GamePanel extends JPanel implements Runnable, KeyListener {
    
	private static final long serialVersionUID = 1L;
	boolean game_running = true;
	
	long delta = 0;
	long last  = 0;
	long fps   = 0;
	
	boolean up    = false;
	boolean down  = false;
	boolean left  = false;
	boolean right = false;
	boolean drop  = false;
	
	int speed = 50;
	int h = 0;
	Sprite player, bomb;
	Sprite blocks[];
	Vector<Sprite> actors;
	BufferedImage[] bombpics;
	
	public GamePanel(int w, int h) {
		this.setPreferredSize(new Dimension(w,h));
		JFrame frame = new JFrame("BomberMJ");
		frame.setLocation(100,100);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.addKeyListener(this);
		frame.add(this);
		frame.pack();
		frame.setVisible(true);
		doInitializations();
	}
	
	private void doInitializations() {
	    int k = 0;
		
		last = System.nanoTime();
		
	    actors = new Vector<Sprite>();
	    BufferedImage[] mjpics = this.loadPics("pics/MJ.gif", 36);
	    BufferedImage[] blockpics = this.loadPics("pics/Block.gif", 1);
	    bombpics = this.loadPics("pics/Bomb.gif", 2);
	    
	    player = new Player(mjpics, 0, 0, 100, this);
	    player.setLoop(1,1);
	    
	    blocks = new Sprite[20];
	    
	    
	    for(int i = 1; i < 8; i = i + 2) {
	    	
	    	for(int j = 1; j < 10; j = j + 2) {
	    		
	    		if(k < blocks.length ) {
	    			blocks[k] = new Block(blockpics, j * 75 , i * 75, 100, this);
	    			actors.add(blocks[k]);
	    			System.out.println(j*75 + "," + i*75 + "," + k);
	    			k++;
	    		}
	    			
	    	}
	    	
	    }
	    
	    actors.add(player);
		Thread t = new Thread(this);
	    t.start();
	}
	
	private BufferedImage[] loadPics(String path, int pics) {
		
		BufferedImage[] anim = new BufferedImage[pics];
		BufferedImage source = null;
		
		URL pic_url = getClass().getClassLoader().getResource(path);
		
		try {
			source = ImageIO.read(pic_url);
		}
		
		catch(IOException e) {
			
		}
		
		for(int x = 0; x < pics; x++) {
			anim[x] = source.getSubimage(x * source.getWidth() / pics, 0, source.getWidth() / pics, source.getHeight());
		}
		
		return anim;
	}
	
	private void dropBomb() {
		bomb = new Bomb(bombpics, player.getX() , player.getY() + 25, 100, this);
		actors.add(bomb);
	}
	
	private void computeDelta() {
		delta = System.nanoTime() - last;
		last  = System.nanoTime();
		
		fps = ((long) 1e9) / delta;
	}
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		
		g.setColor(Color.red);
		g.drawString("FPS: " + Long.toString(fps), 20, 10);
		
		if(actors != null) {
			for(Drawable draw : actors) {
				draw.drawObjects(g);
			}
		}
	}
	
	private void doLogic() {
		
		Vector<Sprite> trash = new Vector<Sprite>();
		Sprite check, s1, s2;
		
		for(Movable mov : actors) {
			mov.doLogic(delta);
			check = (Sprite) mov;
			
			if(check.remove) {
				trash.add(check);
			}
		}
		
		for(int i = 0; i < actors.size(); i++) {
			for(int n = i + 1; n < actors.size(); n++) {
				
				s1 = actors.elementAt(i);
				s2 = actors.elementAt(n);
				
				s1.collidedWith(s2);
			}
		}
		
		if(trash.size() > 0) {
			actors.removeAll(trash);
			trash.clear();
		}
	}
	
	private void moveObjects() {
		for(Movable mov : actors) {
			mov.move(delta);
		}
	}
	
	private void checkKeys() {
		if(drop) {
			dropBomb();
		}
		
		if(up) {
			player.setVerticalSpeed(-speed);
		}
		
		if(down) {
			player.setVerticalSpeed(speed);
		}
		
		if(right) {
			player.setHorizontalSpeed(speed);
		}
		
		if(left) {
			player.setHorizontalSpeed(-speed);
		}
		
		if(!up && !down) {
			player.setVerticalSpeed(0);
		}
		
		if(!left && !right) {
			player.setHorizontalSpeed(0);
		}
	}
	public void run() {
		while(game_running) {
		    computeDelta();
		    checkKeys();
		    doLogic();
		    moveObjects();
		    
		    repaint();
			
			
			try {
				Thread.sleep(10);
			}
			
			catch (InterruptedException e) {}
		}
	}
	public static void main(String[] args) {
		
		new GamePanel(825,675);
	}

	@Override
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
		
		if(e.getKeyCode() == KeyEvent.VK_SPACE) {
			drop = true;
			
		}
		
		if(e.getKeyCode() == KeyEvent.VK_UP) {
			up = true;
			
			if(h != 1) {
				player.setLoop(4, 7);
				h = 1;
			}
		}
		
		if(e.getKeyCode() == KeyEvent.VK_DOWN) {
			down = true;

            if(h != 2) {
            	player.setLoop(0, 3);
            	h = 2;
            }
		}
		
		if(e.getKeyCode() == KeyEvent.VK_LEFT) {
			left = true;
			
			if(h != 3) {
				player.setLoop(12, 15);
				h = 3;
			}
		}
		
		if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
			right = true;
			if(h != 4) {
				player.setLoop(8, 11);
				h = 4;
			}
		}
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
		if(e.getKeyCode() == KeyEvent.VK_SPACE) {
			drop = false;
			
		}
		
		if(e.getKeyCode() == KeyEvent.VK_UP) {
			up = false;
			if(h != 0) {
				player.setLoop(1,1);
				h = 0;
			}
		}
		
		if(e.getKeyCode() == KeyEvent.VK_DOWN) {
			down = false;
			if(h != 0) {
				player.setLoop(1,1);
				h = 0;
			}
		}
		
		if(e.getKeyCode() == KeyEvent.VK_LEFT) {
			left = false;
			if(h != 0) {
				player.setLoop(1,1);
				h = 0;
			}
		}
		
		if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
			right = false;
			if(h != 0) {
				player.setLoop(1,1);
				h = 0;
			}
		}
		
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}

Java:
import java.awt.Graphics;

public interface Drawable {
    
	public void drawObjects(Graphics g);
}

Java:
public interface Movable {
    
	public void doLogic(long delta);
	
	public void move(long delta);
}
 

Gucky

Top Contributor
Für die Kollision gibt es die Polygone. Diese haben die contains(int,int) Methode, mit der man prüfen kann, ob der Punkt im Polygon enthalten ist. Du könntest jedem Objekt ein Polygon geben und diese mit einer Extraklasse laufend mit den Positionen der Figuren abgleichen (die Figuren rufen dann eine entsprechende Methode auf). Wenn die Figur im Objekt enthalten ist, dann gibt die Kollisionsklasse eine Meldung zurück, wenn nicht dann nicht.
 

protectedzone

Aktives Mitglied
Wie finde ich heraus von welcher Seite die Spielfigur mit dem Objekt kollidiert. Wenn zum Beispiel die rechte obere Ecke des Spielers mit dem Objekt kollidiert, weiß man ja nicht, ob die Figur nun von unten oder links kam.

Ich hab das jetzt nicht klar vor Augen, aber die Figur könnte ja während jeder Bewegung speichern, von wo sie kam. Bei einer Kollision braucht man dann nur noch die entsprechende Variable aufzurufen und die Figur entsprechend zurückzusetzen.

Für die Kollisionserkennung reicht bei Bombernman meiner Meinung nach auch ein zweidimensionales Array, das in booleans speichert, ob das Feld 'besetzt' ist. Also sowas: (isOccupied[x][y] == true).
 
Zuletzt bearbeitet:

Gucky

Top Contributor
Wenn es ein Bomberman mit Bewegungen fließenden Bewegungen sein soll, reicht es nicht, meiner Meinung nach. Denn dann kann eine Figur auch mal zur Hälfte auf einem Feld sein. Korrigiert mich, wenn ich falsch liege. :)
 

Mr. Moon

Mitglied
So Thema ist erledigt. Habe den Fehler gefunden und behoben und es hingekriegt, dass ich nicht durch bestimmte Objekte gehen kann indem ich gespeichert habe, von welcher Richtung ich komme.
 

protectedzone

Aktives Mitglied
Wenn es ein Bomberman mit Bewegungen fließenden Bewegungen sein soll, reicht es nicht, meiner Meinung nach. Denn dann kann eine Figur auch mal zur Hälfte auf einem Feld sein. Korrigiert mich, wenn ich falsch liege. :)

Ja, aber ich denke, dass das keine Rolle spielt, wenn man es gescheit programmiert. Auf einem Schachfeld müssen die Figuren ja auch nicht exakt im Zentrum des Feldes stehen, aber besetzen immer ein eindeutiges Feld der 64 möglichen.

Gruss, protectedzone
 

Gucky

Top Contributor
Aber auf einem Schachbrett können die Figuren nicht auf der Grenze zwischen zwei Feldern stehen.

PS: Beim Schreiben dieses Textes fällt mir auf: die Figur könnte dann halt zwei Felder belegen. :D
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
StrikeTom Schwerkraft mit festen objekten darstellen Spiele- und Multimedia-Programmierung 27
T Wie kann ich ein OrbitBehavior auf einen festen Wert setzen? Spiele- und Multimedia-Programmierung 2
M JPanel mit Graphics2D Objekten mit JScrollpane Spiele- und Multimedia-Programmierung 6
BraunBerry Rotation von Objekten um ein Raumschiff Spiele- und Multimedia-Programmierung 6
R Verschieben von Objekten langsam Spiele- und Multimedia-Programmierung 0
S [lwjgl] Renderbug bei mehreren Objekten Spiele- und Multimedia-Programmierung 2
F Kollisionsabfrage bei schnellen Objekten Spiele- und Multimedia-Programmierung 2
P "Tiefe" in Objekten - LWJGL Spiele- und Multimedia-Programmierung 12
W Java3D: Farbe von Objekten stimmt nicht mit übergebenem RGB-Wert überein Spiele- und Multimedia-Programmierung 9
M [Java3D] Animation von mehreren Objekten Spiele- und Multimedia-Programmierung 7
B Kollisionserkennung bei gezeichneten Objekten Spiele- und Multimedia-Programmierung 2
L Platzieren von Objekten auf TileMap Spiele- und Multimedia-Programmierung 6
P Culling von Image-Objekten Spiele- und Multimedia-Programmierung 3
B 1)JButtons zeichnen 2)Kolisionsabfrage von zwei Objekten Spiele- und Multimedia-Programmierung 9
D Array aus Objekten Spiele- und Multimedia-Programmierung 2
V Koordinaten von Objekten? Spiele- und Multimedia-Programmierung 8
J Kollision von Objekten Spiele- und Multimedia-Programmierung 7
J Simulation mit vielen Objekten: Datenbank? Spiele- und Multimedia-Programmierung 6
F Bewegung/Kollision von Objekten auf Tastendruck Spiele- und Multimedia-Programmierung 6
G Bewegen von Objekten Spiele- und Multimedia-Programmierung 4
B Hilfe gesucht!! (bewegen von grafischen Objekten) Spiele- und Multimedia-Programmierung 3

Ähnliche Java Themen

Neue Themen


Oben