2D Shooter (von oben) Kugelberechnung und drehen der Figur

florian1995

Aktives Mitglied
hallo!
ich will einen 2d shooter in einem Jframe programmieren.
dabei soll sich die figur an der maus ausrichten. habs schon gegooglet aber nichts gefunden.
die kugeln sollen bei einem mausklick in richtung maus fliegen.

kann mir jmd ein codebeispiel nennen oder ein tutorial? die figur ist ein image.
 

florian1995

Aktives Mitglied
DOCH!
ich weiß nur nicht wie man die kugeln berechnet und ein image an der maus ausrichtet!! hab mir zwar eine berechnungsmethode ausgedacht diese ist jedoch sehr ungenau
 
T

Tomate_Salat

Gast
naja, das sollte mit einfacher Steigunsberechung funktioneren:

[c]m = (y2-y1)/(x2-x1)[/c]

wobei dann die eine Koordinate deine Figur ist und die andere die Maus. Dann musste dir halt noch [c]b[/c] ausrechnen. Die Formel ist ja bekannt:
[c]f(x) = mx+b[/c] => [c]b = y/mx[/c]

MFG

Tomate_Salat
 

florian1995

Aktives Mitglied
frage: was ist m?
also fasse ich das richtig auf?
m= mausx+mausy/playerx+playery?
kapier das nicht so richtig

ich wollte es so machen das es ein xspeed und ein yspeed gibt
 
G

Gast2

Gast
m ist die Steigung deiner Geraden.

m= mausx+mausy/playerx+playery?
So ist das falsch.
Code:
m = mausy - playery / mausx - playerx
passt schon eher. Du musst allerdings mal schauen wie das passt wenn die maus rechts/links/unten/oben vom player ist.

dein xSpeed und ySpeed ansatz sollte übrigens auch auf nen ähnlichen Ansatz kommen.
 

florian1995

Aktives Mitglied
ok ich brauch jz mal hilfe!
Java:
public Shot(int playerx,int playery,int mousex,int mousey){
 //hier xspeed und yspeed berechnen
}

public void moveShot(){
 x+=xspeed;
 y+=yspeed;
}
hoffe jemand kann mir sagen wie ich das jetzt berechne
 

Steev

Bekanntes Mitglied
Dreieck ? Wikipedia

Im Grunde genommen kannst du das doch über die gängigen Dreieckssätze lösen.
Du hast die Position des Spielers (Mittelpunkt) = P1 und du hast die Position des Cursors = P2. Alle anderen Punkte und Größen kannst du daraus ableiten.
Dann kannst du mithilfe der Winkelsätze den Winkel berechnen und anhand des Winkels das Bild ausrichten. Per AffineTransform z.B. (Achtung: Bogenmaß)

Foundation Flash: - Rotation in AS3

Gruß
Steev
 
Zuletzt bearbeitet:

florian1995

Aktives Mitglied
ok danke für die antwort :D
nur das problem ist das ich erst 15 bin und dadurch noch nicht so viel höhere mathematik behersche.
ich kenne zwar die winkelsätze hab sie aber noch nie in einem game angewendet ;(

ich weiß wie affinetransform funktioniert nur weiß ich nicht wie ich die grad-zahl bekomme
 

Steev

Bekanntes Mitglied
Müsste in etwa so funktionieren: (nicht getestet)

[Java]double ang = Math.atan2(pos1X - pos2X, pos1Y - pos2Y) / (Math.PI / 180);[/Java]

Gruß
Steev
 

Quaxli

Top Contributor
ok danke für die antwort :D
nur das problem ist das ich erst 15 bin und dadurch noch nicht so viel höhere mathematik behersche.
ich kenne zwar die winkelsätze hab sie aber noch nie in einem game angewendet ;(

ich weiß wie affinetransform funktioniert nur weiß ich nicht wie ich die grad-zahl bekomme

Das ist keine höhere Mathemathik. Sinus, Cosinus, Tangens. Die Begriffe hast Du bestimmt schon mal gehört? :D

Das was Du vorhast besteht aus 2 Schritten:

1. Den aktuellen Winkel vom Spieler zum Mauszeiger berechnen und
2. das Ganze wieder rückwärts: Mit Hilfe der gewünschten Geschwindigkeit des Schusses und dem Winkel die x-/y-Geschwindigkeit errechnen.
 

Quaxli

Top Contributor
Wollen wir mal nicht so sein....
Unten ein kleines, einfaches Beispiel, das die Geschichte demonstriert. In dem Fall wird immer aus der linken unteren Ecke geschossen und jeder neue Schuß "resettet" diesen. In einem Spiel mit beweglicher Figur ist das dann natürlich aufwändiger, aber es soll ja nur ein Beispiel sein und Du sollst ja auch noch was zu tun haben.

Java:
import java.awt.event.*;
import java.awt.geom.Rectangle2D;

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

public class ShotExample extends JPanel implements Runnable, MouseMotionListener, MouseListener {

	private static final long	serialVersionUID	= 1L;
	JFrame frame;
	Point target;
	double angle;
	Shot shot;
	boolean fire = false;
	
	public static void main(String[] args) {
		new ShotExample(400,400);
	}
	
	public ShotExample(int i, int j) {
		 frame = new JFrame("ShotExample");
		 frame.setLocationRelativeTo(null);
		 setPreferredSize(new Dimension(i,j));
		 addMouseMotionListener(this);
		 addMouseListener(this);
		 frame.add(this);
		 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		 frame.pack();
		 frame.setVisible(true);
		 
		 target = new Point(0,0);
		 fire = false;
		 
		 Thread th = new Thread(this);
		 th.start();
		 
	}

	public void run() {

		long last = 0;
		long delta = 0;
		last = System.nanoTime();
		
     while(frame.isVisible()){
    	 
    	 delta = System.nanoTime() - last;
    	 last = System.nanoTime();
    	 
    	 computeAngle();
    	 checkShot();
    	 
    	 if(shot!=null){
      	 shot.move(delta);
    	 }
    	 
    	 try {
				Thread.sleep(10);
			} catch (InterruptedException e) {}
    	
			repaint();
    	 
     }
		
	}
	
	
	private void computeAngle(){
		
		double dx = target.getX();
		double dy = getHeight()-target.getY();
		
		//Java rechnet mit Radians, daher Tangens nach Grad umrechnen
		angle = Math.toDegrees(Math.atan2(dx, dy));

	}
	
	private void checkShot(){
		
		if(!fire){
			return;
		}
		fire = false;
		shot = new Shot(0,getHeight(),angle);
		
	}
	
	public void paintComponent(Graphics g){
		super.paintComponent(g);
		g.setColor(Color.RED);
		
		if(shot!=null){
			g.drawRect((int)shot.x,(int)shot.y,(int)shot.width,(int)shot.height);
		}
	}
	
	public void mouseDragged(MouseEvent e) {
		
	}

	public void mouseMoved(MouseEvent e) {
		target = e.getPoint();
	}

	public void mouseClicked(MouseEvent e) {
		
		
	}

	public void mouseEntered(MouseEvent e) {
		
		
	}

	public void mouseExited(MouseEvent e) {
		
		
	}

	public void mousePressed(MouseEvent e) {
		
		
	}

	public void mouseReleased(MouseEvent e) {
		fire = true;
	}
	

}

class Shot extends Rectangle2D.Double{
	
	private static final long	serialVersionUID	= 1L;
	final static int SIZE = 10;
	final static int SPEED = 200;
	
	double dx;
	double dy;

	public Shot(int sx, int sy, double dir){
		super(sx-SIZE/2,sy-SIZE/2,SIZE,SIZE);
		computeDeltas(dir);
	}
	
	private void computeDeltas( double d){
		//Sinus u. Cosinus ausrechnen. Hypothenuse ist die Geschwindigkeit
		//evtl. einfach mal ausmalen
		dx = Math.sin(Math.toRadians(d)) * SPEED;
		dy = Math.cos(Math.toRadians(d)) * SPEED;
		dy *= -1; //Bewegung nach oben - daher y invertieren
	}
	
  public void move(long delta) {
    if (dy != 0) {
        y += dy * (delta / 1e9);
    }
    
    if (dx != 0) {
        x += dx * (delta / 1e9);
    }
}
	
}
 

florian1995

Aktives Mitglied
so habs jetzt getestest.
Java:
public Shot(int x, int y,int mouse_x,int mouse_y,GamePanel p){
        this.x=x;
        this.y=y;
        this.p=p;
        double dx = mouse_x;
        double dy = mouse_y;
        if(mouse_x<x){
            dx*=-1;
        }else{
            //startposition des balles vor oder nach der figur
            this.x+=p.radius;
        }
        if(mouse_y<y){
            dy*=-1;
        }else{
            this.y+=p.radius;
        }

        alpha = Math.toDegrees(Math.atan2(dx, dy));
        xspeed = Math.sin(Math.toRadians(alpha)) * maxspeed;
        yspeed = Math.cos(Math.toRadians(alpha)) * maxspeed;
        
        
        
    }

jetzt habe ich das problem dass es einen toten winkel hinter dem spieler gibt.
was ist mein fehler?
 

Quaxli

Top Contributor
Erklär das mal näher aus dem Stück Code werde zumindest ich nicht schlau.
Aus dem Code überigens auch nicht:

Java:
public Shot(int x, int y,int mouse_x,int mouse_y,GamePanel p){
        this.x=x;
        this.y=y;
        this.p=p; //Sinn und Zweck dieser 3 Anweisungen?
        double dx = mouse_x;
        double dy = mouse_y; 
        //Was ist dx und dy? Scheint sich um einen Bewegungswert zu handeln, aber Du
       //übergibst wohl irgendwie die Mausposition
        if(mouse_x<x){
            dx*=-1;
        }else{
            //startposition des balles vor oder nach der figur
            this.x+=p.radius;
        }
        if(mouse_y<y){
            dy*=-1;
        }else{
            this.y+=p.radius;
        }
 
        alpha = Math.toDegrees(Math.atan2(dx, dy));  //warum hier Math.toDegrees?
        xspeed = Math.sin(Math.toRadians(alpha)) * maxspeed; //hier wird das gerad wieder rückgängig gemacht
        yspeed = Math.cos(Math.toRadians(alpha)) * maxspeed;
        
        
        
    }
 

Samuel72

Aktives Mitglied
Hallo Florian,

ich würde das ganze ohne Winkel machen,
sondern einfach mit dem Steigungsdreieck:

Java:
public Shot(double playerx, double playery, double mousex, double mousey){
 xspeed = (mousex-playerx)/Math.sqrt((playerx-mousex)*(playerx-mousex)+(playery-mousey)*(playery-mousey));
 yspeed = (mousey-playery)/Math.sqrt((playerx-mousex)*(playerx-mousex)+(playery-mousey)*(playery-mousey));

}

public void moveShot(){
 x+=xspeed;
 y+=yspeed;
}
Für die Variablen würde ich grundsätzlich double verwenden, da bei Integern der Wert leicht einmal 0 wird, und dann gibt es gar keine Bewegung.
 

Ähnliche Java Themen

Neue Themen


Oben