#java #gravity
#Ява #гравитация
Вопрос:
Я хочу, чтобы, когда мой плеер сойдет с платформы (в классе PlatformerPanel метода checkCollision ()), он упадет, а затем что-то сделает, когда исчезнет с экрана, я еще не настроил экран окончания игры, но это то, что я планирую сделать. В любом случае, проблема в том, что по какой-то причине он движется слишком быстро и падает слишком рано, а также при нажатии клавиши со стрелкой во время падения он вернется на платформу.
Пожалуйста, попытайтесь помочь мне преодолеть это или придумать новый, простой для понимания способ сделать это/сделать так, чтобы это работало так, как я планирую.
ПРАВКА 1: Я исправил то, что происходит слишком рано, так что не беспокойтесь об этом
``` public class PlatformerMain { public static void main(String[] args) { PlatformerGameFrame platformerGame = new PlatformerGameFrame(); } } import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class PlatformerGameFrame extends JFrame{ PlatformerGamePanel panel; PlatformerGameFrame() { panel = new PlatformerGamePanel(); this.add(panel); this.setTitle("Platformer Game"); this.setResizable(false); this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); this.pack(); this.setVisible(true); this.setLocationRelativeTo(null); this.getContentPane().setBackground(new Color(0,0,0)); } } import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class PlatformerGamePanel extends JPanel implements Runnable{ PlatformerPlayer player1; PlatformerMap map1; static final int SCREEN_WIDTH = 1000; static final int SCREEN_HEIGHT = 600; static final int PLAYER_WIDTH = 50; static final int PLAYER_HEIGHT = 60; static final Dimension SCREEN_SIZE = new Dimension(SCREEN_WIDTH,SCREEN_HEIGHT); static boolean falling = false; Image backgroundImage; Thread gameThread; Image image; Graphics graphics; PlatformerMap map; public PlatformerGamePanel() { java.net.URL imgIcon = Main.class.getResource( "/Resources/spaceImage.jpg"); backgroundImage = new ImageIcon(imgIcon).getImage(); newPlayer(); newMap(); this.setFocusable(true); this.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) {} @Override public void keyPressed(KeyEvent e) { player1.KeyPressed(e); } @Override public void keyReleased(KeyEvent e) { player1.KeyReleased(e); } }); this.setPreferredSize(SCREEN_SIZE); this.setOpaque(true); gameThread = new Thread(this); gameThread.start(); } public void paint(Graphics g) { image = createImage(getWidth(),getHeight()); graphics = image.getGraphics(); draw(graphics); g.drawImage(image, 0,0, null); } public void draw(Graphics g) { Graphics2D g2D = (Graphics2D) g; g2D.drawImage(backgroundImage, 0,0, null); player1.paint(g); map.paint(g); } public void newPlayer() { player1 = new PlatformerPlayer((SCREEN_WIDTH/2)-(PLAYER_WIDTH/2), (SCREEN_HEIGHT/2)-(PLAYER_WIDTH/2), PLAYER_WIDTH, PLAYER_HEIGHT); } public void newMap() { map = new PlatformerMap(); } public void checkCollision() { if(player1.x gt; SCREEN_WIDTH-PLAYER_WIDTH) { player1.x = SCREEN_WIDTH-PLAYER_WIDTH; } else if(player1.x lt; 0) { player1.x = 0; } if(!(player1.x gt;map.PLATFORM_WIDTH)) { if(player1.y gt; SCREEN_HEIGHT-250) { player1.y = SCREEN_HEIGHT-250; } } else if(player1.x gt; map.PLATFORM_WIDTH) { gravity(); } } public void falling() { } public void gravity() { player1.gravity(); } public void move() { player1.move(); } public void run() { long lastTime = System.nanoTime(); double amountOfTicks = 120.0; double ns = 1000000000 / amountOfTicks; double delta = 0; while(true) { long now = System.nanoTime(); delta = (now - lastTime)/ns; lastTime = now; if(delta gt;= 1) { move(); checkCollision(); gravity(); repaint(); delta--; } } } } import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class PlatformerPlayer extends Rectangle { /*static int playerPosX = 100; static int playerPosY = 100;*/ static double velocityY = 0; static double velocityX = 0; static int vertical_position; static final int TERMINAL_VELOCITY = 200; static final int PLAYER_WIDTH = 50; static final int PLAYER_HEIGHT = 50; static int speed = 2; protected boolean falling = true; protected boolean jumping = false; double gravity = 0.05; public PlatformerPlayer(int x, int y, int PLAYERWIDTH, int PLAYERHEIGHT) { super(x,y,PLAYERWIDTH,PLAYERHEIGHT); } public void KeyPressed(KeyEvent e) { if(e.getKeyCode()==KeyEvent.VK_LEFT) { setXDirection(-speed); move(); } else if(e.getKeyCode()==KeyEvent.VK_RIGHT) { setXDirection(speed); move(); } } public void KeyReleased(KeyEvent e) { if(e.getKeyCode()==KeyEvent.VK_LEFT) { setXDirection(0); move(); } else if(e.getKeyCode()==KeyEvent.VK_RIGHT) { setXDirection(0); move(); } } public void paint(Graphics g) { Graphics2D g2D = (Graphics2D) g; g2D.setColor(Color.red); g2D.fillRect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT); } public void setYDirection(int YDirection) { velocityY = YDirection; } public void setXDirection(int XDirection) { if(speed gt; 10) { speed = 10; } velocityX = XDirection; } public void move() { y = velocityY; x = velocityX; } public void gravity() { velocityY = gravity; if (velocityY gt; TERMINAL_VELOCITY) { velocityY = TERMINAL_VELOCITY; } vertical_position -= velocityY; } } import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class PlatformerMap extends Rectangle { int PLATFORM_WIDTH = 600; int PLATFORM_HEIGHT = 150; public PlatformerMap() { } public void paint(Graphics g) { Graphics2D g2D = (Graphics2D) g; g2D.setColor(Color.gray); g2D.fillRect(100,400,PLATFORM_WIDTH,PLATFORM_HEIGHT); } }
Комментарии:
1. Трудно дать точный ответ, не прочитав и полностью не поняв весь ваш код (а у меня нет на это времени), поэтому позвольте мне вместо этого дать несколько советов: 1) попробуйте пройти через ваш код с помощью отладчика, чтобы проверить, почему игрок падает слишком рано (установите точку останова в коде, который инициирует падение), 2) как только игрок падает, отключите/игнорируйте любой ввод ключа, который вам не нужен,
2. 3) если ваш игрок падает слишком быстро, проверьте свой расчет силы тяжести:
velocityY = gravity;
кажется неправильным, так как отсутствует компонент времени (есть разница между добавлением 0,05 к скорости каждые 10 мс или каждые мс и т.д.). Вы обновляете состояние игры только один раз за тик, но обратите внимание, чтоdelta
оно может быть gt; 1, поэтому любое движение должно учитывать это для плавной анимации. 4) Обратите внимание, что вы в основном звонитеgravity()
дважды, если игрок падает: 1checkCollision();
раз, а затем снова непосредственно в вашем основном цикле.3. Спасибо вам за то, что вы сделали все возможное, не глядя на мой код, я приму во внимание то, что вы сказали, но я все еще ищу ответ, в котором кто-то может посмотреть на мой код и предложить свои предложения.