New at Java, need help coding movement

Oct 5, 2014 at 5:38 PM
Um... Chosen One? Yeah that'll work. : P
"..."
Join Date: Aug 3, 2014
Location: worm hole
Posts: 362
Age: 22
I'm going at this the wrong way I bet, but I've tried to make a thing using all my Java knowledge learnt in two days that's meant to be like a green square moving smoothly when keys are pressed.
It works, but it stutters and looks ugly.

Ideas would be neat.

Code:
Code:
package redabsol0.Game1.Main;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

@SuppressWarnings("serial")
public class Game1Main extends JFrame implements Runnable, KeyListener
{
	Thread t;
	static int i = 0;
	static boolean isDebugging = true;
	static boolean isPinging = false;
	static int gameState = 0;
	
	public static int x = 10, y = 100;
	
	static Game1Main main;

	Game1Main()
	{
		main = this;
		t = new Thread(this, "Game Runtime");
		t.start();

		final JPanel p = new JPanel();
		p.setBackground(Color.RED);

		if (isDebugging)
		{
			JMenuBar bar = new JMenuBar();
			JMenu debug = new JMenu("Debug");
			bar.add(debug);
			JMenuItem bgColorChange = new JMenuItem("Change content pane");
			bgColorChange.addActionListener(new ActionListener()
			{
				@Override
				public void actionPerformed(ActionEvent arg0)
				{
					if(gameState == 0)
					{
						p.setBackground(Color.BLUE);
						gameState = 1;
					}
					else
					{
						p.setBackground(Color.RED);
						gameState = 0;
					}
				}
			});
			JMenuItem quit = new JMenuItem("Quit");
			quit.addActionListener(new ActionListener()
			{
				@Override
				public void actionPerformed(ActionEvent arg0)
				{
					System.exit(0);
				}
			});
			debug.add(bgColorChange);
			debug.add(quit);

			bar.add(debug);

			this.setJMenuBar(bar);
		}
		this.setUndecorated(true);
		this.setExtendedState(JFrame.MAXIMIZED_BOTH);
		this.setVisible(true);

		this.add(p);
	}

	public static void main(String args[])
	{
		new Game1Main();
		while (true)
		{
			if (isPinging)
			{
				i++;
			}
		}
	}

	public void run()
	{
		addKeyListener(this);
		while (true)
		{
			repaint();
			if (isPinging)
			{
				System.out.println("Ping: " + Integer.toString(i / 1000000));
				i = 0;
				try
				{
					Thread.sleep(1000);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
			}
		}
	}

	public void paint(Graphics g)
	{
		super.paint(g);
		
		g.setColor(Color.GREEN);
		g.fillRect(x, y, 100, 100);
	}

	@Override
	public void keyPressed(KeyEvent e)
	{
		if(e.getKeyCode() == KeyEvent.VK_D)
		{
			x+=10;
		}
		if(e.getKeyCode() == KeyEvent.VK_A)
		{
			x-=10;
		}
		if(e.getKeyCode() == KeyEvent.VK_W)
		{
			y-=10;
		}
		if(e.getKeyCode() == KeyEvent.VK_S)
		{
			y+=10;
		}
	}

	@Override
	public void keyReleased(KeyEvent e)
	{
		
	}

	@Override
	public void keyTyped(KeyEvent e)
	{
		
	}
}
Unless I'm doing something crucially impacting to the universe or this thing I want to do with my coding style, don't comment on it.

All I request is help making movement look smooth.
 
Oct 5, 2014 at 5:43 PM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
protip: use
Code:
 tags so i can actually see the formatting
 
Oct 5, 2014 at 6:56 PM
Senior Member
"Wahoo! Upgrade!"
Join Date: Aug 11, 2014
Location:
Posts: 57
What do you mean by stutter? Is it very short, fine stutters? Frequent? Rare? Choppy?

My knowledge of Java is not great, so I'm most likely missing an obvious problem. In general, I would avoid using threads if you can help it.

EDIT:
in your main, you have a loop that just says "while (true)" with no sleep on it. I don't know if that's the cause, but that will eat your processor alive (at least in C++ it does) and I can easily imagine it causing some lag.
 
Oct 5, 2014 at 7:53 PM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
Doing the while(true) thing is probably not a great idea, as fluffball says.
I'd recommend just throwing it into a scheduled timer, for example:
Code:
class GameCanvas extends JPanel {
    GameCanvas() {
    ...
    Timer gametimer;
        gametimer = new Timer(1000/60, (event) -> {
            engine.updateState(keyHandler.getUpdate());
            engine = engine.getNextState();
            repaint();
        });
        gametimer.start();
    ....
    }
}
where engine is something that implements this interface
Code:
public interface DisplayableState {
    public void updateState(KeyUpdate update);
    public void draw(Graphics g);
    public DisplayableState getNextState();
}
and KeyHandler.getUpdate() returns an object showing which keypress events have occurred since the last time it was called.
It's a pretty basic game logic but it should handle a simple 2D game.
Also, you're moving the box 10 pixels at a time? I imagine that would not look great.
 
Oct 6, 2014 at 6:27 PM
Um... Chosen One? Yeah that'll work. : P
"..."
Join Date: Aug 3, 2014
Location: worm hole
Posts: 362
Age: 22
Fluffball said:
What do you mean by stutter? Is it very short, fine stutters? Frequent? Rare? Choppy?
Well, basically since I'm using repaint(); it makes the square I'm drawing disappear every time it updates, which of course means that there's that flash of red that doesn't look great.

I'm thinking of making a separate class or something and using paintComponent() which might look better.
 
Oct 6, 2014 at 7:40 PM
Senior Member
"Wahoo! Upgrade!"
Join Date: Aug 11, 2014
Location:
Posts: 57
Oh... I've been using double buffering for so long in directX that I forgot it wasn't a given...

Research double buffering to make sure that's your problem, and if it is, try to go ahead and implement it.
 
Oct 6, 2014 at 9:36 PM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
ok so I ran your code
for one, that's flickering, not stuttering

For two, you're drawing things wrong. You have a JPanel, which is acting as your background, and then trying to draw directly to the JFrame underneath it for the square on top.

Code:
...
		final JPanel p = new GameCanvas();
...
	private class GameCanvas extends JPanel {
		
		@Override
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			
			g.setColor(Color.GREEN);
			g.fillRect(x, y, 100, 100);
		}
	}
that clears up your flickering issue
Swing components are hierarchy so when you add something to a container it goes inside and on top of it.
 
Oct 7, 2014 at 7:55 AM
Um... Chosen One? Yeah that'll work. : P
"..."
Join Date: Aug 3, 2014
Location: worm hole
Posts: 362
Age: 22
Noxid said:
ok so I ran your code
for one, that's flickering, not stuttering

For two, you're drawing things wrong. You have a JPanel, which is acting as your background, and then trying to draw directly to the JFrame underneath it for the square on top.


Code:
...		final JPanel p = new GameCanvas();...	private class GameCanvas extends JPanel {				@Override		public void paintComponent(Graphics g) {			super.paintComponent(g);						g.setColor(Color.GREEN);			g.fillRect(x, y, 100, 100);		}	}
that clears up your flickering issue
Swing components are hierarchy so when you add something to a container it goes inside and on top of it.
Sweet, thanks Noxid.
 
Top