(GRA) skok postaci nie tylko w góre, jak ? I kolizje

0

Witam. Udało mi się wreszcie stworzyc funkcje, która umożliwia w miarę płynny skok postaci.

  1. Pierwszy problem polega na tym, ze skacze tylko góra dół i nie wiem jak zrobić, żeby podczas skoku można było ruszać się w prawo / lewo.
  2. Drugi to kolizje. Postać podczas skoku, gdy natrafi na przeszkodę na chwile zatrzymuje się pod nią, zaś następnie leci nadal w górę. Nie mam pojęcia ja to rozwiązać. Dodam, że funkcja opowiadająca za kolizje działa, niestety nie wiem jak zaimplementować ją przy skoku i przy spadaniu.

Proszę o jakąkolwiek pomoc.

Cała klasa Gameplay :

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;


public class ElectricManGameplay extends JPanel implements  KeyListener, ActionListener
{
	
	
		
	
	
	
	
	Textury box = new Textury("box.png", 600, 670, 200, 270);
	Postać postać = new Postać("Postać.png", 100, 680, 70, 70, 40, 70);
	
	private ImageIcon picture;

	private static final int LeftMapBorder = 21;
	private static final int RightMapBorder = 1405 ;
	private static final int TopMapBorder = 21;
	private static final int BottomMapBorder = 750;
	
	
	
	
	private int moves = 0;
	private int delay = 100;
	private int t = 1;
	
	
	
	private boolean left = false;
	private boolean right = false;	
	private boolean jump = false;
	private boolean down = false;
	

	private Timer timer;
	
	public ElectricManGameplay()
	{
		
		addKeyListener(this);
		setFocusable(true);
		setFocusTraversalKeysEnabled(false);
		timer = new Timer(delay, this);
		timer.start();	
	}
	
	
	public void Jump()
	{
			if(jump)
			{		
						postać.Yposition = 4*t*t - postać.Jump*t + 743;
				    	t++;
				    	System.out.println(t + "  "+ postać.Yposition);
					
				   
					if(postać.Yposition > 680)
					{
						postać.Yposition = 680;
						jump = false;
						t=1;
					}
			}	
	} 
	
	
	
	public static boolean Kolizja(Postać postać, Textury box)
	{
		return(postać.Xposition < box.rightSide && postać.Xposition + postać.Width > box.leftSide && postać.Yposition + postać.Height > box.topSide &&  postać.Yposition < box.bottomSide);
	}
	

	public void paint(Graphics g) 
	{
	
		if(moves == 0)
		{
			postać.Xposition = 100;
			postać.Yposition = 680;
		}
		
		g.setColor(Color.black);
		g.drawRect(20, 20, 1455, 730);
		
		g.setColor(Color.white);
		g.fillRect(21, 21, 1454, 729);
		
		
		picture = new ImageIcon(postać.NazwaPliku); //rysowanie postaci
		picture.paintIcon(this,g , postać.Xposition, postać.Yposition);
	
	
		picture = new ImageIcon(box.NazwaPliku); // rysowanie przeszkody
		picture.paintIcon(this,g, box.leftSide, box.topSide);
		
		
		//picture = new ImageIcon(box.NazwaPliku); // rysowanie przeszkody
		//picture.paintIcon(this,g, box.leftSide, box.topSide);
		
		
		
			
	}


	public void keyPressed(KeyEvent e)
	{
		
		
		if(e.getKeyCode() == KeyEvent.VK_RIGHT) // jeśli przycisk (prawa strzałka) jest wciśnięty to wykonaj instrukcje
		{
			moves ++;
			right = true;
			left = false;		
			jump = false;
			down = false;
		}
			
		 if(e.getKeyCode() == KeyEvent.VK_LEFT)
		{
			moves ++;
			right = false;
			left = true;			
			jump = false;
			down = false;
		}
		 
		 
		 
		 if(e.getKeyCode() == KeyEvent.VK_UP)
			{
				moves ++;
				right = false   ;
				left = false;
				jump = true;
				down = false;
			}
		 
		 
		 
		 if(e.getKeyCode() == KeyEvent.VK_DOWN)
			{
				moves ++;
				right = false;
				left = false;
				jump = false;
				down = true;
			}
	
			
		 if(e.getKeyCode() == KeyEvent.VK_1)
			{
				postać.Prędkość=60;
			}
			if(e.getKeyCode() == KeyEvent.VK_2)
			{
				postać.Prędkość=80;
			}
			if(e.getKeyCode() == KeyEvent.VK_3)
			{
				postać.Prędkość=100;
			}
			
	}


	public void keyReleased(KeyEvent e)
	{
		
		right = false; 
		left =  false;
		down =  false;
	
	}


	public void keyTyped(KeyEvent e)
	{
		
		
	}


	public void actionPerformed(ActionEvent e) 
	{
		
		
		if(right)
		{		
			
			postać.Xposition += postać.Prędkość;	
	
		
			if(postać.Xposition > RightMapBorder)
			{
				postać.Xposition = RightMapBorder;
		
			}
			
			
			if(Kolizja(postać, box)==true)
			{
				postać.Xposition = box.leftSide  - postać.Width;
				
			}
			
			System.out.println("Xpos:[" + postać.Xposition + "] X1pos:[" + (postać.Xposition+postać.Width) + "]" + "Ypos:[" + postać.Yposition + "] Y1pos:[" + (postać.Yposition+postać.Height) + "]" + "  Kolizja:  " + Kolizja(postać, box));
		
		}
		
		
		
		if(left)
		{
			postać.Xposition -= postać.Prędkość;
			
			if(postać.Xposition < LeftMapBorder)
			{
				postać.Xposition = LeftMapBorder;
			
			}
			
			if(Kolizja(postać, box)==true)
			{
				
				postać.Xposition = box.rightSide;
		
			}
			System.out.println("Xpos:[" + postać.Xposition + "] X1pos:[" + (postać.Xposition+postać.Width) + "]" + "Ypos:[" + postać.Yposition + "] Y1pos:[" + (postać.Yposition+postać.Height) + "]" + "  Kolizja:  " + Kolizja(postać, box));
		}
		
			
		if(jump )
		{
			Jump();
			if(Kolizja(postać, box)==true)
			{
				postać.Yposition = box.bottomSide;
			}
			
			if(postać.Yposition < TopMapBorder)
			{
				postać.Yposition = TopMapBorder;
			}
			
			System.out.println("Xpos:[" + postać.Xposition + "] X1pos:[" + (postać.Xposition+postać.Width) + "]" + "Ypos:[" + postać.Yposition + "] Y1pos:[" + (postać.Yposition+postać.Height) + "]" + "  Kolizja:  " + Kolizja(postać, box));
		}
		
		
		
		if(down)
		{
			postać.Yposition += postać.Prędkość;
		
			if(postać.Yposition + postać.Height > BottomMapBorder)
			{
				postać.Yposition = BottomMapBorder-70;
			}
			
			if(Kolizja(postać, box)==true)
			{
				postać.Yposition = box.topSide - postać.Height;
			}
			
			System.out.println("Xpos:[" + postać.Xposition + "] X1pos:[" + (postać.Xposition+postać.Width) + "]" + "Ypos:[" + postać.Yposition + "] Y1pos:[" + (postać.Yposition+postać.Height) + "]" + "  Kolizja:  " + Kolizja(postać, box));
			
		}
		
		repaint();
		}
	
	}

A to klasa postać :

public class Postać 
{
	public String NazwaPliku;
	public int    Xposition;
	public int    Yposition;
	public int    Width;
	public int    Height;
	public int    Prędkość;
	public int 	  Jump; //wysokość skoku (W zakresie 67 - 107)
public Postać(String N, int X, int Y, int W, int H, int P, int J)
{
 NazwaPliku = N;
	 
	 // punkt A(Xposition, Yposition)
	 Xposition =  X;
	 Yposition =  Y;
	 Width =      W;
	 Height =     H;
	 Prędkość =   P;
	 Jump = J;
	 
}
}

0
if(e.getKeyCode() == KeyEvent.VK_UP)
            {
                moves ++;
                right = false   ;
                left = false;
                jump = true;
                down = false;
            }

Tak na szybko to tutaj leży błąd.
Pierw sprawdzasz czy strzałki są prawo/lewo i je ustawiasz, potem wchodzisz do strzałki w górę i resetujesz zarówno lewo i prawo.
Aby to wyeliminować najprościej wszystkie falsy powinny być na samym początku przed sprawdzaniem jakie klawisze są wciśnięte, najlepiej w metodzie np. resetKeysStatuses czy coś.

Dodatkowo zmienna t, czym to jest? Słaba opcja dla nazwy zmiennej, formatowanie tragiczne (Twoje IDE powinno to trochę poprawić, zobacz auto formatowanie), nazwy metod w javie piszemy z małej litery, wywołujesz metodę Jump a w niej sprawdzasz czy jump == true, czytelniej jest pierw to sprawdzić. To tak na szybko co jeszcze mi się rzuciło w oczy.

0
  1. Po prostu zmodyfikuj kod tak aby podczas skoku dało się ruszać w lewo/prawo.

  2. W momencie zetknięcia z górną przeszkodą, trzeba ustawić prędkość pionową na 0.

Polecam obejrzeć

Kolizję z otoczeniem najlepiej jest badać, zanim w ogóle wykonasz ruch. Sprawdzasz, czy wektory przesunięcia kolidują po drodze z jakąś przeszkodą (Raycast). Jeśli tak, to obcinasz je do długości przy której nie ma kolizji i zerujesz prędkość w tym kierunku.

2

Normalnie się używa dwóch wektorów gdzie pierwszy to transform, położenie x,y,z i rotacja x,y,z.
Drugi to vektor prędkości x,y,z.

Kolizje to dość złożony problem, od zwykłych kolizji brył, po raytracing pocisków itp.

Przydałby ci się silnik fizyczny, ala rigidbody, taki silnik traktuje kolizje obiektu jako jakiś obiekt, afsalt, lód(różne współczynniki tarcia między obiektami) dzięki czemu zwalnia w zależności od podłoża, poruszanie się, a poruszanie jest zwykłym kopniakiem w dupę.
W dodatku w zależności od orientacji kolizji dany vektor prędkości jest zerowany lub odwracany z jakimś procentem siły.

0

@Kermii: Ale wszystkie zmienne są ustawione defaultowo na false'y, dlatego nie wiem co tutaj można jeszcze poprawić. Próbuje jakos zmodyfikować tę część ale cos nie idzie. Sprobowalem cos takiego

 if(e.getKeyCode() == KeyEvent.VK_UP)
			{
				moves ++;
				
				if(jump = true)
				{
					right = true;   
					left =  true;
					down = false;
				}
				else
				{
					right = false;   
					left =  false;
					down = false;
				}
			}

i tutaj



	public void actionPerformed(ActionEvent e) 
	{
if(jump&&right)
		{
			Jump();
			postać.Xposition+=100;
		}
		
		
		
.
.
.
.
}

Zaczęło się przesuwać w prawo przy skoku ale gdy puszcze jump to zostaje w miejscu. Nie mam już pomysłów.

0

@Spwr1111:
Jak chcesz proste rozwiązanie do Twojego problemu, to tutaj taki pseudo kod

keyPressed() {
    resetAllDirections(); // set them to false
    if (keyUp) {
        up = true;
    } 
    if (keyLeft) {
       left = true;
    }
    ......
}

Pewnie lepiej na switchu to zrobić, ogólnie nie ma sensu w każdym warunku innych kierunków ustawiać na false, zrób to raz dla wszystkich kierunków przed wszystkimi warunkami (ifami).

EDIT:
Jump nie powinien w żaden sposób być zainteresowany tym czy jest right, left czy nic. Jedna funkcja ma być jumpem i zmieniać tylko pozycję Y, w innym miejscu zmieniaj pozycję X dla ruchu lewo/prawo

1

Posluchaj przedmowcy, zrob na wektorach. Daje Ci to potem najwieksze mozliwosci tuningowania tego co sie dzieje, a jak ogarniesz co i jak to nie jest trudne.

1 użytkowników online, w tym zalogowanych: 0, gości: 1