2D-Grafik Koordinaten nicht immer die selben

Weed

Mitglied
Hallo.
Als erstes mal... Ich bin neu hier, ich hoffe ich mach jetzt nichts falsch oder so.
Hab bezüglich meines Problems nichts gefunden, also wäre es sehr net wenn mir jemand helfen könnte.

Kurze Vorgeschichte: Bin noch recht unwissend mit Java. Hab zwar schon einige Erfahrungen gesammelt (1.Jahr an einer EDV Schule Java-Basics, Plugins für Minecraft) hab aber noch viel zu lernen.

Ich möchte mir ein Jump-and-Run Game schreiben. Läuft auch im Moment alles gut bis auf ein Problem. Bin noch recht am Anfang deshalb nervt mich das recht. 🙂
Also ich will ein Image auf ein Panel zeichnen. Hört sich ja eigentlich leicht an was es eigentlich auch ist. Nur meine Koordinaten sind immer verschieden. Sie sind anders wenn ich sie in einer Methode zuweise und auch wenn ich nur eine if-Anweisung darüber habe.
Ich komm einfach nicht drauf was das Problem ist.
Hier Code + Pics:

So wie ich es haben will (Pic):
ImageShack® - Online Photo and Video Hosting
Aber nur mit diesem Code:
Java:
    private void startGame(String player) {
        currentPlayer = player;
        pnMainMenu.setVisible(false);
        this.remove(pnMainMenu);
        this.add(pnGame);
        pnGame.setSize(800, 600);
        pnGame.setVisible(true);
        this.setSize(806, 603);
        Dimension screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        int posX = (screen.width / 2) - 403;
        int posY = (screen.height / 2) - 301 - 50;
        setLocation(posX, posY);
        repaint();
        running = true;
        firstRun = true;
        Thread playerMoveThread = new Thread(new MovePlayer(sf));
        playerMoveThread.start();
        repaint();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g = pnGame.getGraphics();

        if (running == true) {
            int level = Player.getLevel(currentPlayer);
            Level.loadLevel(level, g);
            Graphics2D g2d = (Graphics2D) g;
            Rectangle playerRect = new Rectangle(altX, altY, 25, 22);
            g2d.setColor(pnGame.getBackground());
            g2d.draw(playerRect);
            g2d.fill(playerRect);
                playerX = 30;
                playerY = pnGame.getHeight() - 47;
                altX = playerX;
                altY = playerY;
                firstRun = false;
            g2d.drawImage(playerImg, playerX, playerY, 25, 22, pnGame);
        }
    }

Nun da ich aber die Variablen nicht bei jedem repaint() auf diese Werte setzen will, dachte ich mir ich mach einer boolean Variable die sagt das programm läuft zum ersten mal und nur dann setzt er die variablen so.

Gesagt getan:
Java:
    private void startGame(String player) {
        currentPlayer = player;
        pnMainMenu.setVisible(false);
        this.remove(pnMainMenu);
        this.add(pnGame);
        pnGame.setSize(800, 600);
        pnGame.setVisible(true);
        this.setSize(806, 603);
        Dimension screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        int posX = (screen.width / 2) - 403;
        int posY = (screen.height / 2) - 301 - 50;
        setLocation(posX, posY);
        repaint();
        running = true;
        firstRun = true;
        Thread playerMoveThread = new Thread(new MovePlayer(sf));
        playerMoveThread.start();
        repaint();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g = pnGame.getGraphics();

        if (running == true) {
            int level = Player.getLevel(currentPlayer);
            Level.loadLevel(level, g);
            Graphics2D g2d = (Graphics2D) g;
            Rectangle playerRect = new Rectangle(altX, altY, 25, 22);
            g2d.setColor(pnGame.getBackground());
            g2d.draw(playerRect);
            g2d.fill(playerRect);
            if(firstRun == true){
                playerX = 30;
                playerY = pnGame.getHeight() - 47;
                altX = playerX;
                altY = playerY;
                firstRun = false;
            }
            g2d.drawImage(playerImg, playerX, playerY, 25, 22, pnGame);
        }
    }

Doch die Koordinaten sind falsch:
ImageShack® - Online Photo and Video Hosting

Gut Gut Warum setz ich die Variablen nicht gleich in der Start methode?
Ergebnis:
ImageShack® - Online Photo and Video Hosting

Mit diesem Code:
Java:
    private void startGame(String player) {
        currentPlayer = player;
        pnMainMenu.setVisible(false);
        this.remove(pnMainMenu);
        this.add(pnGame);
        pnGame.setSize(800, 600);
        pnGame.setVisible(true);
        this.setSize(806, 603);
        Dimension screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        int posX = (screen.width / 2) - 403;
        int posY = (screen.height / 2) - 301 - 50;
        setLocation(posX, posY);
        repaint();
        running = true;
        firstRun = true;
        playerX = 30;
        playerY = pnGame.getHeight() - 47;
        altX = playerX;
        altY = playerY;
        firstRun = false;
        Thread playerMoveThread = new Thread(new MovePlayer(sf));
        playerMoveThread.start();
        repaint();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g = pnGame.getGraphics();

        if (running == true) {
            int level = Player.getLevel(currentPlayer);
            Level.loadLevel(level, g);
            Graphics2D g2d = (Graphics2D) g;
            Rectangle playerRect = new Rectangle(altX, altY, 25, 22);
            g2d.setColor(pnGame.getBackground());
            g2d.draw(playerRect);
            g2d.fill(playerRect);
            g2d.drawImage(playerImg, playerX, playerY, 25, 22, pnGame);
        }
    }

Ich versteh das nun wirklich nicht.

Zusatzinfo:
OS: Win7 64bit
IDE: Netbeans 7.0

Hoffe jemand kann mir helfen.
Danke im Vorraus.
Weed
 
Zuletzt bearbeitet:
warum machst du das so kompliziert mit den Bilden, es geht doch offensichtlich nur um den Wert von pnGame.getHeight()?
was pnGame ist wird übrigens nirgendwo gesagt?
gib doch jeweils aus was pnGame.getHeight() ist..

direkt am Anfang ist immer schwer, Komponenten-Koordinaten abzufragen,
erst muss das Layout asynchron vom AWT-Thread durchgeführt werden,

zur Verschiebung noch eine Idee:
pnGame.setSize(800, 600);
pnGame.setVisible(true); // erstes repaint irgendwann mit Höhe 600
this.setSize(806, 603); // sorgt irgendwann,z.B. beim zweiten paint dafür, dass das enthaltene pnGame nur noch Höhe 580 hat weil 20 Pixel
für deinen schwarzen Rand oder die Titelleiste des JFrames draufgehen, je nachdem was 'this' ist, auch das klärst du nicht,
falls ein JFrame, war das vorher schon sichtbar?


die Zeile
> g = pnGame.getGraphics();
ist nicht dein Ernst, oder?
wenn in pnGame was zu malen ist, dann mit der dortigen paint-Methode, diese Methode kann ja gerne ihr Graphics-Parameter-Objekt herumreichen,
der Thread mit repaint muss dann pnGame repainten,
 
Ja sorry hab vergessen das alles zu erwähnen. 😳
pnGame ist das Panel auf dem das Spiel abläuft.
This ist hier meine MainKlasse und ist ein Frame. Es ist vorher sichtbar und wenn das Spiel startet nehm ich einfach das andere Panel raus und setze das Panel (pnGame) ein.

Das mit der paint Methode versteh ich gerade nicht ganz. Kannst du mir das bitte nochmal etwas besser erklären? sorry bin ein anfänger.

Achja danke schon mal 😉
 
> Das mit der paint Methode versteh ich gerade nicht ganz.

ich verstehe nicht ganz, was du daran nicht ganz verstehst, eine vollständige Frage wäre etwas besser
 
Was meinst du damit:

>die Zeile
>> g = pnGame.getGraphics();
>ist nicht dein Ernst, oder?
>wenn in pnGame was zu malen ist, dann mit der dortigen paint-Methode, diese Methode kann ja >gerne ihr Graphics-Parameter-Objekt herumreichen,
>der Thread mit repaint muss dann pnGame repainten,
 
das ist zwar nicht gerade viel Text von dir, aber schon ein hilfreicher Hinweis, ich dachte du beziehst dich auf das andere
mit den ersten paint-Aufrufen bis dann irgendwann die Size festgelegt ist 😉

zum anderen Punkt ganz grundsätzlich:
es gibt Lehrbücher zu Java und Beispiele, was steht dort?
dass die paint-Methode sicher nicht ohne Grund ein Graphics-Objekt als Parameter hat,
paint wird aufgerufen (nicht von dir), Graphics g kommt als Parameter, in Graphics g wird gezeichnet,
einfaches Konzept, oder?
nirgendwo wirst du Anfängerbeispiele mit getGraphics() von einer anderen Komponente finden,
damit ist quasi alles gesagt, mehr Details will ich gar nicht nennen,

jede Komponente malt in sich selber per paint, niemand anders malt von woanders aus in der Komponente, fertig

wenn du übrigens repaint() am JFrame aufrufst, dann wird auch die paint-Methode von pnGame ausgeführt,
bzw. bei Swing generell eher an paintComponent() denken, ganz wie in allen Beispielen auf der Welt nachzulesen,
das sollte ich gar nicht schreiben müssen..
 
Zuletzt bearbeitet von einem Moderator:
Ja sorry kenn mich halt nicht so aus 🙁
Danke

Hätte da noch ne Frage. Wie soll ich nun die Größen setzen damit mein Panel genau 800x600 pixel hat?

EDIT: Ok habs gelöst.
 
Zuletzt bearbeitet:
Eh du kannst bei dem Panel die größe setzen.
ruf auf das Panel setPreferredSize(new Dimension(800,600) auf.

Danach musst du sorge dafür tragen, dass das fenster sich an die größe der in ihm befindlichen Components anpasst.
Das geht mit
Java:
<JFramename>.pack();
Allerdings gibt das manchmal Probleme beim Aufsetzen komplexer GUIs, da pack sich glaube ich nicht von selbst in den Swing Thread depatched.
Sprich wenn du ein Fenster komplex aufbaust und dann einfach pack() aufrufst kann das ziemlich merkwürdige Ergebnisse geben - da der Swing Thread noch mit den LayoutManager aktionen beschäftigt sein könnte (beispielsweise) und dann die Fenstergröße einem Zwischenstand entspricht.

Daher kannst du da einen kleinen workaround reinnehmen.. ist so nicht sehr schön aber mir fällt da keine bessere Lösung ein, wenn jmd was schöneres hat immer her damit 😀
Java:
final JFrame finalSelfRef = this;
SwingUtilities.invokeLater(new Runnable(){
  @Override
  public void run(){
    finalSelfRef.pack();
  }
});
kann sein das daoben fehler drin sind, ich habs grad heir im Browser geschrieben, die Idee sollte klar sein: durch SwingUtilities.invokeLater([...]) "dispatched" du den aufruf von pack() zu dem Zeitpunkt, bei welchem die bisherigen Aktionen im Thread abgeschlossen sind - das sollte also nach dem "auslegen" der componenten aufgerufen werden (damit meine ich den getContentPane().add([...]) kram..)

Hoffe das hilft ;-)

MfG
Daniel
 
Jo danke, hätte geholfen, bin aber selbst drauf gekommen 😉
Trotzdem danke 🙂
 
Zuletzt bearbeitet von einem Moderator:
Hi,

ich bin zwar generell kein Freund von Frameworks, aber dieses hier kann ich dir wirklich nur empfehlen wenn du in Java ein Spiel schreiben willst:

Golden T Studios - Java Game Developer World

Es ist zwar schon lange nicht mehr ge-updated worden, dafür ist es einfach zu verstehen und zu verwenden, relativ performant und es gibt direkt auf der Seite ein paar gute Einsteiger-Tutorials. Nur grundlegende Java-Sprachkenntnisse werden vorausgesetzt. Kannst es dir ja mal ansehen, ich habe bereits damit gearbeitet (ist schon etwas länger her), ist durchaus brauchbar 🙂


Gruß,


Alan
 

Neue Themen


Zurück
Oben