Bild berührt Bild

Krypthor

Aktives Mitglied
Hi,
ich bin dabei mir ein kleines Spiel zum Test zu machen,
allerdings bin ich gerade auf ein Problem gestoßen;
Ich hab 2 Spieler (der eine lenkt mit Pfeiltasten der andere mit wasd),
und wenn die sich berühren soll der Berührte bzw. der auf den es festgelegt ist, unsichtbar werden.
Ich hab keine Ahnung wie man das macht, dass wenn ein Pixel eines Bildes den Pixel eines anderen Bildes berührt, eine Aktion stattfindet, deshalb hab ich das etwas umständlich geplant (ich bin Anfänger 😀).
Und ich weis nicht wenn man ein Bild hat, wo die "Haupt" Koordinate dieses Bildes ist,
wird es ab unten links, oben links oder ab der Mitte an gezeichnet?

Wenn es ab unten links an wäre hätte ich es so geplant:
Java:
if((p.x * p.y >= (p2.x * p2.y)) && (p.x * p.y <= ((p2.x + 10) * (p2.y + 10)))){
//Code
}
10 * 10 ist das Bild groß, p ist Player1 und p2 ist Player2.
Wenns ab der Mitte gezeichnet würde hätte ich das Bild in 4 Teile zerlegt.

Also;
- von wo wird das Bild gezeichnet (unten links,mitte....)?
- gibt es eine einfachere Methode bzw. eine die ich auch als Anfänger verstehe?

Vielen Dank schonmal für Hilfe,
Krypthor
 
Es wird von oben links aus gezeichnet. Für den Überschneidungstest... den kann man per Hand (ziemlich trivial) selbst implementieren, aber ... wenn du für deine Spiel-Objekte eine eigene Klasse hast (*räusper* 😉) könnte es eine Methode geben
boolean collidesWith(GameObject other) { ... }
die man implementieren kann, wie man will - im zweifelsfall kann man dann auch zwei Rectangle-Objekte erstellen, und mit
this.rectangle.intersects(other.rectangle);
feststellen, ob sie sich überschneiden.
 
Cool, ich weis nur noch nicht wie und wo ich das jetzt einfügen muss^^
also ich hab zwei klassen für Player1 und 2 und ein "Interface" wo alles zusammengefügt wird.
 
Gleiche Frage, nur

ich hab eine Actor-Klasse, eine Mob-Klasse und eine Level-Klasse

jetzt möchte ich erst mal die kollision zwischen einem Objekt der Mob-Klasse mit der Actor-Klasse prüfen

ist es sinnvoll dies in der Actor-Klasse zu machen oder eher in der Mob-Klasse ?!
da die Actor-Klasse ja dann ganz viele Mob-Objekte überprüfen müsste,
oder jedes Mob-Object einmal mit der Actor-Klasse
 
irgendwie klappt das bei mir nicht,
ich hab in der klasse von spieler 1 jetzt stehen :
Java:
	public Rectangle getBounds(){
		return new Rectangle(x, y, 14, 18);
	}
und von spieler 2 das gleiche.

Im Interface also da wo alles zusammengefügt wird hab ich das stehen
Java:
	public void checkCollisions(){
		Rectangle r1 = p.getBounds();
        Rectangle r2 = p2.getBounds();
        if (r1.intersects(r2)){System.out.print("test");}
        if(r2.intersects(r1)){System.out.print("test2");
        }
	}
klappt aber nicht?!
 
Naja, ob Rechtecke oder Kreise ist da ja fast egal... wenn es um Bilder geht, kann man gleich Rechtecke nehmen.

Poste mal ein stück compilier- und ausführbaren Code, in dem man das (unzureichend beschriebene) "klappt nicht" nachvollziehen kann. Sicher, dass du nicht z.B. Component.getBounds überschrieben hast oder so...?
 
Naja am besten wirds wohl sein ich poste einfach mal meinen gesamten Code:

Start:
Java:
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;


public class Start {
	
	public Start(){
		JFrame frame1 = new JFrame();
		frame1.add(new Interface());
		frame1.setLocation(100,100);
		frame1.setSize(600,400);
		frame1.setTitle("War");
		frame1.setResizable(false);
		frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame1.setVisible(true);
	}

public static void main(String[] args){
	new Start();
	}
}

Player:
Java:
import java.awt.Image;

import javax.swing.ImageIcon;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;


import java.awt.Image;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

import javax.swing.ImageIcon;

public class Player{
	int x, y, dx, dy, nx, nx2, left;
	Image still;
	ImageIcon i = new ImageIcon("Bilder/Spielersteht.png");
	ImageIcon ls = new ImageIcon("Bilder/SpielerseiteLsteht.png");
	ImageIcon rs = new ImageIcon("Bilder/SpielerseiteRsteht.png");
	ImageIcon ud = new ImageIcon("Bilder/Spieler.gif");
	ImageIcon l = new ImageIcon("Bilder/SpielerseiteL.gif");
	ImageIcon r = new ImageIcon("Bilder/SpielerseiteR.gif");
	
	public Player(){
		still = i.getImage();
		x = 30;
		y = 180;
	}
	
	public Rectangle getBounds(){
		return new Rectangle(x, y, 14, 18);
	}
	
	public void move(){	
		if (x <= 0){
			x = x + 1;
		}
		if(x >= 580){
			x = x - 1;
		}
		if (y <= 0){
			y = y + 1;
		}
		if(y >= 355){
			y = y - 1;
		}
		if(x == 122 && y >= 49 && y <= 322){
			x = x - 1;
		}
			x = x + dx;
			y = y + dy;
	}
	
	
	public int getX(){
		return x;
	}
	public int getY(){
		return y;
	}
	public Image getImage(){
		return still;
	}

	public void keyPressed(KeyEvent e){
		int key = e.getKeyCode(); 
	
		if (key == KeyEvent.VK_LEFT){
			dx = -1;
			still = l.getImage();
		}
		if (key == KeyEvent.VK_RIGHT){
			dx = +1;
			still = r.getImage();
		}
		if (key == KeyEvent.VK_UP){
			dy = -1;
			still = ud.getImage();
		}
		if (key == KeyEvent.VK_DOWN){
			dy = +1;
			still = ud.getImage();
		}
		if (key == KeyEvent.VK_P){
		}
	}

	public void keyReleased(KeyEvent e){
		int key = e.getKeyCode(); 
	
		if (key == KeyEvent.VK_LEFT){
			dx = 0;
			still = ls.getImage();
		}
		if (key == KeyEvent.VK_RIGHT){
			dx = 0;
			still = rs.getImage();
		}
		if (key == KeyEvent.VK_UP){
			dy = 0;
			still = i.getImage();
		}
		if (key == KeyEvent.VK_DOWN){
			dy = 0;
			still = i.getImage();
		}
		//System.out.print(x + "=x ");
		//System.out.print(y + "=y ");
	}
	
}

Player2:
Java:
import java.awt.Image;
import java.awt.Rectangle;

import javax.swing.ImageIcon;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;


import java.awt.Image;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;

public class Player2{
	int x, y, dx, dy, nx, nx2, left;
	Image still2;
	ImageIcon i = new ImageIcon("Bilder/Spielersteht.png");
	ImageIcon ls = new ImageIcon("Bilder/SpielerseiteLsteht.png");
	ImageIcon rs = new ImageIcon("Bilder/SpielerseiteRsteht.png");
	ImageIcon ud = new ImageIcon("Bilder/Spieler.gif");
	ImageIcon l = new ImageIcon("Bilder/SpielerseiteL.gif");
	ImageIcon r = new ImageIcon("Bilder/SpielerseiteR.gif");

	public Player2(){
		still2 = i.getImage();
		x = 550;
		y = 180;
	}
	
	public Rectangle getBounds(){
		return new Rectangle(x, y, 14, 18);
	}

	public void move(){	
		if (x <= 0){
			x = x + 1;
		}
		if(x >= 580){
			x = x - 1;
		}
		if (y <= 0){
			y = y + 1;
		}
		if(y >= 355){
			y = y - 1;
		}
			x = x + dx;
			y = y + dy;
	}
	
	
	public int getX(){
		return x;
	}
	public int getY(){
		return y;
	}
	public Image getImage(){
		return still2;
	}

	public void keyPressed(KeyEvent e){
		int key = e.getKeyCode(); 
	
		if (key == KeyEvent.VK_A){
			dx = -1;
			still2 = l.getImage();
		}
		if (key == KeyEvent.VK_D){
			dx = +1;
			still2 = r.getImage();
		}
		if (key == KeyEvent.VK_W){
			dy = -1;
			still2 = ud.getImage();
		}
		if (key == KeyEvent.VK_S){
			dy = +1;
			still2 = ud.getImage();
		}
	}

	public void keyReleased(KeyEvent e){
		int key = e.getKeyCode(); 
	
		if (key == KeyEvent.VK_A){
			dx = 0;
			still2 = ls.getImage();
		}
		if (key == KeyEvent.VK_D){
			dx = 0;
			still2 = rs.getImage();
		}
		if (key == KeyEvent.VK_W){
			dy = 0;
			still2 = i.getImage();
		}
		if (key == KeyEvent.VK_S){
			dy = 0;
			still2 = i.getImage();
		}
	}
}

Interface:
Java:
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import java.awt.Image;
import java.util.ArrayList;

public class Interface extends JPanel implements ActionListener{
Player p;
Player2 p2;
Image img2;
Timer time;

	public Interface(){
		p = new Player();
		p2 = new Player2();
		addKeyListener(new AL());
		addKeyListener(new AL2());
		setFocusable(true);
		ImageIcon i = new ImageIcon("Unbenannt.png");
		img2 = i.getImage();
		time = new Timer(5, this); 
		time.start();
	}
	
	public void actionPerformed(ActionEvent e) {
		p.move();
		p2.move();
		repaint();
	}
	
	public void checkCollisions(){
		Rectangle r1 = p.getBounds();
        Rectangle r2 = p2.getBounds();
        if (r1.intersects(r2)){
        	System.out.print("jo");
		}
        if(r2.intersects(r1)){
        	System.out.print("jo");
        }
	}
	
	public void paint(Graphics g) {
		
		super.paint(g);
			Graphics2D g2d = (Graphics2D) g;
			g2d.drawImage(img2, 0, 0, null);
			g2d.drawImage(p.getImage(), p.x, p.y, null);
			g2d.drawImage(p2.getImage(), p2.x, p2.y, null);
	}
	
	private class AL extends KeyAdapter{
		public void keyReleased(KeyEvent e){
			p.keyReleased(e);
		}
		public void keyPressed(KeyEvent e){
			p.keyPressed(e);
		}
	}
	private class AL2 extends KeyAdapter{
		public void keyReleased(KeyEvent e){
			p2.keyReleased(e);
		}
		public void keyPressed(KeyEvent e){
			p2.keyPressed(e);
		}
	}
}
 
:autsch: Immer, wenn man denkt, ... *durchatme*... Es sollte nur EINE Spieler-Klasse geben. Die beiden Klassen sind ja komplett gleich - es sind nur zwei unterschiedliche Objekte der gleichen Klasse, mit unterschiedlichen Ausprägungen der Eigenschaften, aber das eine ist ein Spieler und das andere ist ein Spieler... Auch sonst liegt da einiges im Argen, aber zur eigentlichen Frage: Laut Browsersuche (STRG+F) wird "checkCollisions" nirgendwo aufgerufen.........
 
ah das mit dem berühren hab ich jetzt hinbekommen, aber was ist daran falsch mit zwei spielerklassen zu arbeiten?
Ist doch eigentlich nur umständlicher?!
Wie könnte ich mir denn eine sparen?
 
Indem man die zweite löscht 😉 Im Ernst: Der Sinn von Klassen ist ja, dass man beschreibt, wie eine bestimmte Klasse von Objekten aufgebaut ist. Wenn man ein MMOPRG mit 100000 Spielern hat, will man ja nicht 100000 Klassen erstellen, sondern EINE, von der es dann 100000 instanzen gibt. In diesem Fall sollte irgendwo sowas stehen wie
Java:
Player player0 = new Player("red");
Player player1 = new Player("green");
oder so.

Und es geht noch weit darüber hinaus: Ein wichtiger Aspekt bei der Objektorientierten Programmierung ist es, Gemeinsamkeiten zwischen Klassen zu finden, und diese Abstrakt zu beschreiben. Z.B. könnte es ja sein, dass du ein Spiel schreiben willst, wo es mehrere Spieler geben kann (d.h. mehr als ZWEI 😉) und es sowohl Computer- als auch menschliche Spieler geben kann. Dann würde man sowas machen wie
Java:
interface Player
{
    void paintThisPlayerInto(Graphics g);
    Point getPosition();
    void moveOneStep();
}
oder was eben ALLE Spieler gemeinsam haben, und dann z.B. eine abstrakte Basisklasse erstellen
Java:
abstract class AbstractPlayer implements Player
{
    void paintThisPlayerInto(Graphics g) { ... implementieren ... }
    Point getPosition() { ... implementieren ... }

    abstract void moveOneStep(); // Die bleibt noch abstrakt
}
und als konkrete Implementierungen dann
Java:
class HumanPlayer extends AbstractPlayer implements Player
{
    void moveOneStep() {
        // mache Bewegung mit einem KeyListener
    }
}

class ComputerPlayer extends AbstractPlayer implements Player
{
    void moveOneStep() {
        // mache Bewegung mit einer KI
    }
}

Das entscheidende ist, dass man dann z.B. 10 Spieler gegeneinander spielen lassen kann
Java:
List<Player> players = new ArrayList<Player>();
for (int i=0; i<9; i++)
{
    players.add(new ComputerPlayer()); // 9 Computergegner
}
players.add(new HumanPlayer()); // und ein menschlicher Spieler

Ohne dass man 10 Klassen erstellen muss
Java:
class ComputerPlayer0 {
    // 1000 Zeilen code
}

class ComputerPlayer1 {
    // 1000 Zeilen code - die gleichen wie oben
}

class ComputerPlayer2 {
    // 1000 Zeilen code - die gleichen wie oben
}

...

Das "schwierigste" in diesem Fall ist es, die KeyListener richtig mehreren menschlichen Spielern zuzuordnen, aber das ist auch kein Hexenwerk....
 
Hört sich logisch an, ich werds aber erst nochmal so lassen wie ich es habe, da ich einfach noch nicht genug Erfahrungen mit der Programmierung habe um sowas umzusetzen.
Aber vielen Dank für deine Hilfe!

EDIT:
Noch mal ne kurze Frage,
ich habe versucht ein Menü zu erstellen aber es hat irgenwie nicht ganz geklappt.
Das Menü verschwindet zwar und die Spielfläche wird sichtbar, aber man kann den Spieler nicht bewegen?!

Java:
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;


public class Start {
	
	ImageIcon img11 = new ImageIcon("Bilder/Start.png");
	
	public Start(){
		
		final JLabel labelstart = new JLabel(img11);
		labelstart.setBounds(10, 10, 100, 30);
		labelstart.setVisible(true);
		
		final JFrame frame1 = new JFrame();
		frame1.setLocation(100,100);
		frame1.setSize(600,400);
		frame1.setTitle("War");
		frame1.setResizable(false);
		frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame1.add(labelstart);
		frame1.setVisible(true);
		
		
		
		labelstart.addMouseListener(new MouseListener() {

			@Override
			public void mouseClicked(MouseEvent e) {

				frame1.add(new Interface());
				labelstart.setVisible(false);
			}

			@Override
			public void mouseEntered(MouseEvent e) {
				
			}

			@Override
			public void mouseExited(MouseEvent e) {
				
			}

			@Override
			public void mousePressed(MouseEvent e) {
				
			}

			@Override
			public void mouseReleased(MouseEvent e) {
				
			}
			
		});
	}

public static void main(String[] args){
	new Start();
	}
}
 
Zuletzt bearbeitet:
Klick' ggf mal kurz in die Compoenent, wo der KeyListener dranhängt. Wenn der KeyListener danach geht, ist's ein Focusproblem, da kann man ggf. mit component.requestFocus() was machen.
 
Ne geht trozdem nicht....ich wüsste auch nicht woran es liegen könnte?!
Ich kenn mich da leider noch nicht genug aus.
 
Zuletzt bearbeitet:
Wie bevor das Menü gewählt wurde?
Also vorher gings dann hab ich das Menü hinzugefügt und wenn ich jetzt das Programm starte öffnet sich das Menü und wenn man auf das Bild Start klickt wird es unsichtbar und das Interface öffnet sich
aber man kann die Spieler nicht bewegen.
 
Ja, ist halt nicht so systematisch, vermutlich müßte man es sich mal zusammenkopieren und testen, aber du kannst mal schauen, ob statt des
labelstart.setVisible(false);
ein
frame.remove(labelstart);
nicht angebrachter wäre (besser wäre ein CardLayout, oder irgendein anderes Konzept (man erreicht erstaunlich viel, indem man einfach Quellcode hinschreibt, aber irgendwann nicht mehr))

EDIT: Wobei das auf den KeyListener nicht viel Einfluß haben sollte.... ich werd's bei Gelegenheit mal testen, wenn es sich nicht von selbst erledigt...
 
Ja, sowas wie
Java:
            @Override
            public void mouseClicked(MouseEvent e) {
                frame1.remove(labelstart);
                Interface i = new Interface();
                frame1.add(i);
                i.requestFocus();
                frame1.validate();
            }
einzufügen löst zwar vermeintlich das Problem aber... ich hab' das Gefühl, dass du mit diesem "Code hinschreiben der Sachen macht"-Ansatz nicht sooo weit kommen wirst...
 
Ja, um so ein erstes Gefühl zu bekommen, mag das ja OK sein. Aber setz' dir nicht das Ziel, genau dieses Spiel "perfekt bis zum Ende" durchzuprogrammieren....
 
Noch ne kleine Frage, lohnt sich jetzt nicht extra deswegen ein Thread aufzumachen^^

Wenn ich eine Taste drücke soll der Gegenspieler bei Kontakt K.O. gehen. Das klappt auch ganz gut,
nur man könnte diese Taste durchgehend drücken und dadurch wäre sie wiederum sinnlos.
Wie kann ich die für 1 oder 2 sek. "deaktivieren"?
 
Hm... da gibts mehrere mehr oder weniger ausgefeilte möglichkeiten. Eine sehr einfache wäre, sich beim Tastendruck eine Zeit zu speichern und beim nächsten zu überprüfen
Java:
private long lastPressMS = -1;


.... 
void keyPressed(...)
{
    long current = System.currentTimeMillis();
    if (lastPressMS == -1  || current > lastPressMS + 3000) {
        lastPressMS = current;
        killOpponent();
   }
}
 
Das klappt zwar wenn man die Taste danach loslässt aber wenn man sie gedrückt hält bekommt der Gegner ohne Pause Leben gezogen. Das liegt daran das ich den boolean der für den Schaden verantwortlich ist erst wieder auf false setzte, wenn die Tast losgelassen wird.
Wie kann man vielleicht wenn man die Taste drückt den boolean auf true setzen, und nach ungefähr 1s automatisch wieder auf false setzen?
 
Das kommt davon wenn man den zusammenhang nicht richtig beschreibt. Was machst du wo wann mit welchen booleans in keyPressed, keyTyped und keyReleased?
Man könnte einen Timer starten, aber das klingt krampfig, und als wollte man ein Problem lösen, das man selbst verursacht hat...
 

Zurück
Oben