# Jump'N'Run Hügel



## Krypthor (27. Nov 2011)

Hallo,

ich habe neulich mal angefangen ein kleinen Spiel(Jump and Run) nach einem Tutorial zu Programmieren.
Wiederholen könnte ich zwar nicht was ich da alles gemacht habe, aber ich hab zumindest alles soweit verstanden. Ich hab jetzt schon einen Spieler der wenn er nach rechts läuft ab einem bestimmten punkt nicht mehr weiter kann, und stattdessen der Hinterfrund nach links verschoben wird. 

Meine Frage: wie kann man Hügel bzw solche Plattformen festlegen, dass wenn man draufspringt der Charakter oben stehen bleibt(wie bei Mario)? Es reicht wenn die erstmal Rechteckig sind.
Im Prinzip sowas : 
	

	
	
		
		

		
			





Hier mein bisheriger Code:

Frame:

```
public class Frame {

	public Frame(){
		JFrame frame = new JFrame();
		frame.add(new Board());
		frame.setTitle("2D Spiel");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(600,365);
		frame.setVisible(true);
		frame.setResizable(false);
		frame.setLocationRelativeTo(null);
	}
	
	public static void main(String[] args) {
		new Frame();
	}
}
```

Spieler:

```
public class Spieler{
	int x, y, dx, dy, nx, nx2, left;
	Image still;
	ImageIcon i = new ImageIcon("src/Bilder/SpielerstehtR.png");
	ImageIcon i2 = new ImageIcon("src/Bilder/SpielerstehtL.png");
	ImageIcon l = new ImageIcon("src/Bilder/Spieler.gif");
	ImageIcon l2 = new ImageIcon("src/Bilder/SpielerL.gif");
	ImageIcon j = new ImageIcon("src/Bilder/Spielerjump.gif");

	public Spieler(){
		still = i.getImage();
		left = 150;
		x = 75;
		nx2 = 685;
		nx = 0;
		y = 172;
	}

	
	public void move(){
		if (dx != -1){
			if (left + dx <= 150){
				left = left + dx;
				}
				else{	
					x = x + dx;
					nx2 = nx2 + dx;
					nx = nx + dx;
					}
		}
		else
			{
				if (left + dx > 0)
					left = left + dx;
			}
	}
	
	
	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 = l2.getImage();
		}
		if (key == KeyEvent.VK_RIGHT){
			dx = +1;
			still = l.getImage();
		}
		if (key == KeyEvent.VK_UP){
			dy = 1;
			still = j.getImage();
		}
	}

	public void keyReleased(KeyEvent e){
		int key = e.getKeyCode(); 
	
		if (key == KeyEvent.VK_LEFT){
			dx = 0;
			still = i2.getImage();
		}
		if (key == KeyEvent.VK_RIGHT){
			dx = 0;
			still = i.getImage();
		}
		if (key == KeyEvent.VK_UP){
			dy = 0;
			still = i.getImage();
		}
	}
}
```

Board:

```
public class Board extends JPanel implements ActionListener, Runnable{
Spieler p;
Image img;
Timer time;
Thread animator;
int v = 172;
	public Board() {
		p = new Spieler();
		addKeyListener(new AL());
		setFocusable(true);
		ImageIcon i = new ImageIcon("src/Bilder/Unbenannt.png");
		img = i.getImage();
		time = new Timer(5, this); 
		time.start();
	}
	
	public void actionPerformed(ActionEvent e) {
		p.move();
		repaint();
	}
boolean k = false;
	public void paint(Graphics g) {
		if (p.dy == 1 && k == false)
		{
			k = true;
			animator = new Thread(this);
			animator.start();
		}
		super.paint(g);
			Graphics2D g2d = (Graphics2D) g;
			if ((p.getX() - 590) % 2400 == 0){
				p.nx = 0; }
			if ((p.getX() - 1790) % 2400 == 0){
				p.nx2 = 0; }
			g2d.drawImage(img, 685-p.nx2, 0, null);
			if (p.getX() >= 590){
				g2d.drawImage(img, 685-p.nx, 0, null); }
			g2d.drawImage(p.getImage(), p.left, v, null);
	}
	
	private class AL extends KeyAdapter{
		public void keyReleased(KeyEvent e){
			p.keyReleased(e);
		}
		public void keyPressed(KeyEvent e){
			p.keyPressed(e);
		}
	}

	@Override
	public void run() {
		long beforeTime, timeDiff, sleep;
		
		beforeTime = System.currentTimeMillis();
		while(done == false)
		{
			cycle();
			timeDiff = System.currentTimeMillis() - beforeTime;
			sleep = 10 - timeDiff;
			if (sleep < 0){
				sleep = 2; }
			try {
				Thread.sleep(sleep);
			} catch (Exception e){}
			beforeTime = System.currentTimeMillis();
		}
		done = false;
		h = false;
		k = false;
		}
	boolean h = false;
	boolean done = false;
	public void cycle(){
		if (h == false) {
			v--; }
		if (v == 125){
			h = true; }
		if (h == true && v <= 172){
			v++;}
		if (v == 172){
			done = true;
		}
	}
}
```

Ich bedanke mich schonmal für Antworten!


----------



## SkonroX (27. Nov 2011)

position des spielers auslesen, object der platform auslesen mit der position -> abfrage in loop einbauen (z.B. wenn spieler_rectangle.intersects(platform_rectangle) dann -> spieler = fällt nicht mehr


----------



## c_sidi90 (27. Nov 2011)

SkonroX hat gesagt.:


> position des spielers auslesen, object der platform auslesen mit der position -> abfrage in loop einbauen (z.B. wenn spieler_rectangle.intersects(platform_rectangle) dann -> spieler = fällt nicht mehr



Naja ein bisschen mehr gehört schon dazu, ein Spielerobjekt kann ja auch frontal in berührung mit der Plattform kommen. Du musst abfragen, ob die Y Koordinate des Spielers >= der der Plattform ist und der Spieler mit der Plattform kollidiert. Dann setzt du z.B. eine boolean Variable "falling" auf =false so das der Y Wert des Spielers nicht wieder inkrementiert wird solange er auf der Plattform steht Stichwort "Gravity".


----------



## Krypthor (27. Nov 2011)

gibt es da irgendein Tutorial wie man soetwas macht oder die Position des Spielers und soweiter festlegt?


----------



## c_sidi90 (27. Nov 2011)

Ob es für deine konkrete Anwendung ein Tutorial gibt weiss ich nicht, jedoch gibt es auch vorgefertigte GameEngines dafür. Empfehlen kann ich dir die Slick2D Engine basierend auf LWJGL. Wenn du es jedoch selber machen willst, musst du dich bei deiner Suche nicht auf Java Spiele beschränken. Versuch mal nach Schlagwörtern wie "Sidescroller", "Plattformer" in  Verbindung mit "Java" oder "#C" zu googlen. Bin mir sicher du findest dort Tutorials für Mario-clons


----------



## Krypthor (28. Nov 2011)

hi, danke für die antwort, ich hab zwar etwas gefunden, doch verstehen tue ich davon relativ wenig 
vielleicht sollte ich erstmal kleiner anfangen. Allerdings hätte ich trozdem eine Frage dazu;

http://fivedots.coe.psu.ac.th/~ad/jg/ch062/ch6-2.pdf
hier auf s.22 ist unten der Levelaufbau mit Zahlen als Bild angegeben. Gibt es dazu vielleicht ein deutsches Tutorial?
Was genau bedeuten die Zahlen? und wie verbindet man das mit dem Hintergrundbild?


----------



## c_sidi90 (28. Nov 2011)

ohne mir das jetzt angeschaut zu haben, bin ich mir ziemlich sicher, dass dies eine Lösungsmöglichkeit ist ein Level zu laden. Es wird in der 2D Programmierung häufig so gelöst, dass Objekte z.B. Plattformen als eine eindeutige Zahl definiert werden. Es gibt dann eine Klase z.B. Levelloader die eine Textdatei Zeichenweise einliest und prüft um was für ein Zeichen es sich handelt. 

Beispiel: 

Lese Zeile 1 Zeichen 1 : gelesenes Zeichen = 1 >> zeichne einen Block . 

Musst du dir halt mal durchlesen dein Tutorial, sollte dort ja erklärt werden was damit gemeint ist.


----------



## Krypthor (28. Nov 2011)

Gibt es vielleicht dazu ein gutes deutsches Tutorial, ich kann zwar Englisch, jedoch ist es nicht das beste und wenn ich da jede 5te Vocabel übersetzen muss dauert das ewig


----------



## c_sidi90 (28. Nov 2011)

Wüsste ich jetzt für dieses konkrete Beispiel keins. Hab auf youtube jedoch eine Tutorialreihe gefunden, welche mit der von mir bereits erwähnten GameLib Slick2D arbeitet. Hier wird das selbe Verfahren mit Textdateien angewendet, jedoch für einen Spaceinvaders Clon. Lernen kannst du davon aufjedenfall.

Kanal von CrazyandCoding - YouTube


----------



## Krypthor (28. Nov 2011)

Okay, mal angenommen ich wollte ein Fenster machen wo man einen Charakter auf einem 10x10 Feld bewegt:

```
final short level[] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 
  0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
  0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
  0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
  0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
```

(ungefähr so solls aussehen, also jetzt kein Jump and run, sondern aus der Vogelperspektive)
Auf den Feldern 1 soll man sich nicht bewegen können(also eine Mauer).
Wie kann ich das jetzt z.B. machen?
Wie setzt man Bilder an die Punkte und macht sie gleichzeitig "unpassierbar"?
Und wie macht man den Rand außenrum auch "unpassierbar"?

Wäre nett wenn ihr mir das mit nem Beispiel zeigen könntet (wenn es keine Umstände macht  )


----------



## Stelufl (30. Nov 2011)

Galileo Computing :: Java ist auch eine Insel - index


----------



## Plopo (30. Nov 2011)

Hallo,
Ich programmiere auch gerade ein kleines 2D Spiel in Java und verwende dabei den "Leveleditor".

Dein String (mit dem Level (0,1 etc.)) wird folgend ausgelesen und verarbeitet.
Das ist die Datei.
Ein level ist 25x25 Blöcke groß.
Ein Block ist 20x20px groß.

# = Wand
$ = Münze
0 = Tür/Level Ende
@ = Spieler Startposition
n = Zeilenumbruch


```
#########################n
                         n
                         n
   #                     n
                 #       n
                         n
          #              n
                         n
                         n
                         n
                         n
                         n
                         n
                 #       n
   #                     n
                         n
             0           n
           $ #           n
         $ #             n
       $ #               n
     $ #                 n
   $ #                   n
   #                     n
@                        n
#########################
```

Nun ließt man einfach die Datei aus. Zeichen für Zeichen.

```
int tempX = 0;
    int tempY = 0;
    
    for (int i = 0; i < level.length (); i++)
    {
      char item = level.charAt (i);

      if (item == '@')
      {
        guy = new Guy (tempX, tempY, panelWidth, panelHeight);
        tempX += 20;
      }
      else if(item == 'n')
      {
        tempX = 0;
        tempY += 20;
      }
      else if(item == '#')
      {
        Wall wall = new Wall(tempX, tempY);
        walls.add (wall);
        tempX += 20;
      }
      else if(item == ' ')
      {
        tempX += 20;
      }
      else if(item == '0')
      {
        door = new Door(tempX, tempY);
        tempX += 20;
      }
      else if(item == '$')
      {
        Coin coin = new Coin(tempX, tempY);
        coins.add (coin);
        tempX += 20;
      }
    }
```

Die Wand und Münzen werden in einer ArrayList gespeichert, damit man diese später durchlaufen kann zum Zeichnen.

Gezeichnet werden die Wände/Münzen ganz einfach hiermit.

```
for(Wall wall : walls) //Druchläuft die ArrayList
    {
      g.drawImage (wall.getImage (), wall.getX (), wall.getY (), this);
    }
```

Für die "Collision detection" durchläufst du nun auch jedes mal die ArrayList von den "Wänden" und vergleichst die Position der Wand mit der Position deiner Spielfigur.

PS: Keine Ahnung ob das noch einfacher geht, aber es funktioniert.
Für Verbessungsvorschläge bin ich offen  will ja schließlich was lernen.


----------

