Sprite Movement in Java - java

I started learning java as a hobby a little while back because I wanted to make a little game. I learned the basics of java, and I decided that I would try to tackle game-dev. My JFrame and all is fine and I technically have no bugs, but my little rectangle guy won't move around the screen. Here's my code:
package main;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class Race extends JFrame {
public int speed=5;
public int up=1;
public int left=2;
public int down=3;
public int right=4;
public int direction=0;
Rectangle p1 = new Rectangle (500,400,20,40);
public Race()
{
super("Race");
setSize(1000,800);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cont=getContentPane();
cont.setBackground(Color.orange);
setResizable(false);
}
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.red);
g.fillRect(p1.x, p1.y, p1.width, p1.height);
}
public class Move extends Thread implements KeyListener
{
public void run()
{
addKeyListener(this);
while(true)
{
try
{
repaint();
if(direction==up)
{
p1.y-=(int)speed;
}
if(direction==down)
{
p1.y+=(int)speed;
}
if(direction==right)
{
p1.x+=(int)speed;
}
if(direction==left)
{
p1.x-=(int)speed;
}
Thread.sleep(75);
}
catch (Exception e)
{
break;
}
}
}
#Override
public void keyPressed(KeyEvent event) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent event) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent event) {
// TODO Auto-generated method stub
if(event.getKeyChar()=='w')
{
direction = up;
}
if(event.getKeyChar()=='d')
{
direction = left;
}
if(event.getKeyChar()=='s')
{
direction = down;
}
if(event.getKeyChar()=='a')
{
direction = left;
}
}
}
public static void main(String[] args)
{
new Race();
}
}

There are a couple of problems:
You aren't creating a Move instance so nothing is listening to keys.
I don't think you even need a Move class that runs in a background thread. Take the KeyListener logic and put it in your Race class, then "enable" the keyListener by calling addKeyListener(this); so it starts listening to key presses.
Race extends JFrame implements KeyListener{
Race(){
...
addKeyListener(this);
}
#Override
public void keyTyped(KeyEvent event) {
if(event.getKeyChar()=='w')
{
direction = up;
}
if(event.getKeyChar()=='d')
{
direction = left;
}
if(event.getKeyChar()=='s')
{
direction = down;
}
if(event.getKeyChar()=='a')
{
direction = left;
}
repaint();
}
Also see this SO question : Unresponsive KeyListener for JFrame for more help.

If you call the Move class like this in the Race class:
public Move move;
and then call it under you Race constructor:
move = new Move();
in you Move class you make a constructor like this:
public Move()
{
run();
}
This should make it move :)
And for heads up, you need to change the keypress d to go to the right instead of left.

Related

Why the character in my 2D game is not moving?

My program has 3 java files, namely Frame, Dude(which contains the character) and Board(which implements the actionListener). My program is not throwing any error and the images(background and character) are rendering good. But the character is not moving forward.
import javax.swing.*;
public class Frame {
public static void main(String[] args){
JFrame frame= new JFrame("2D Game");
frame.add(new Board());
frame.setVisible(true);
frame.setSize(1200, 600);
}
}
import java.awt.*;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class Dude {
int x, dx, y;
Image still;
public Dude(){
ImageIcon i = new ImageIcon("/home/amitabh/Pictures/man1.jpg");
still= i.getImage();
x=10;
y=172;
}
public void move(){
x=x+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;
if(key== KeyEvent.VK_RIGHT);
dx= 1;
}
public void keyReleased(KeyEvent e){
int key= e.getKeyCode();
if(key==KeyEvent.VK_LEFT);
dx=0;
if(key==KeyEvent.VK_RIGHT);
dx=0;
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Board extends JPanel implements ActionListener{
Image img;
Timer time;
Dude p;
public Board(){
p= new Dude();
addKeyListener(new AL());
setFocusable(true);
ImageIcon i= new ImageIcon("/home/amitabh/Pictures/game1.png");
img= i.getImage();
time= new Timer(5,this);
time.start();
}
#Override
public void actionPerformed(ActionEvent e) {
p.move();
repaint();
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d= (Graphics2D)g;
g2d.drawImage(img, 0,0, null);
g2d.drawImage(p.getImage(), p.getX(), p.getY(), null);
}
public class AL extends KeyAdapter{
public void keyReleased(KeyEvent e){
p.keyReleased(e);
}
public void KeyPressed(KeyEvent e){
p.keyPressed(e);
}
}
}
Start by talking a very close look at:
if (key == KeyEvent.VK_LEFT);
Does that look funny to you?
if (key == KeyEvent.VK_LEFT); // <--- What's the ; doing here?
Change it to be more like...
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
And, yes, this is why you're encouraged to use { ... }
Next, take a closer look at...
public void KeyPressed(KeyEvent e) {
See anything wrong there? Why does it start with an uppercase K, that's not the correct method signature
Change to something more like...
#Override
public void keyReleased(KeyEvent e) {
p.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
p.keyPressed(e);
}
Yes, this is why you're encouraged to use #Override ;)
And finally change your paint method to paintComponent
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
You are encouraged to override paintComponent when performing custom painting, it tends to cause less issues
I'd also encorage you to have a look at the Key Bindings API and favour it over KeyListener as it provides better control of the focus level required to trigger the key events
I'd also encourage your to override getPreferredSize of the Board and return your preferred size from there, rather then setting the frame's size. The frame size includes the frame's decorations, so you content is smaller then the frame size

I cannot draw objects and have them move on the screen

I can draw static things to the screen, but I want to make them move with user key input. I don't know what to do, I've been searching and searching and haven't come up with an answer yet. Please help!
package com.Game.game;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JFrame
{
final static int width = 500;
final static int height = 500;
public int x = 250;
public int y = 250;
public int changeX = 10;
public int changeY = 10;
public static void main(String[] args)
{
new Game();
}
public Game()
{
KeyListener listener = new KeyListening();
addKeyListener(listener);
setFocusable(true);
DrawingStuff drawingstuff = new DrawingStuff();
add(drawingstuff);
setSize(width, height);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public class DrawingStuff extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawString("Hey there!", 300, 300);
g.setColor(Color.RED);
g.fillRect(x, y, 50, 50);
}
}
public class KeyListening implements KeyListener
{
DrawingStuff drawingstuff = new DrawingStuff();
#Override
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_UP)
{
y = y + changeY;
System.out.println("Hey");
drawingstuff.repaint();
}
}
#Override
public void keyReleased(KeyEvent e)
{
}
#Override
public void keyTyped(KeyEvent e)
{
}
}
public void update()
{
}
}
EDIT: Fixed it. I took away the key listener stuff in the constructor method, added a command to focus on "drawingstuff" in the constructor method, and, most importantly, added this bit of code to the end of the constructor method:
while(true)
{
drawingstuff.repaint();
}
The problem is that your KeyListening object has a reference to a different DrawingStuff object than the one you added to your UI inside the Game constructor.
public class KeyListening implements KeyListener
{
DrawingStuff drawingstuff = new DrawingStuff();
...
You should pass a DrawingStuff reference to the KeyListening instance so that it can tell the right object to repaint itself.

How to create a moving object(Dot) on my Jframe (Netbeans)?

Hi guys thanks for your answers ahead of time. I am wondering how i would go about creating a dot and making that dot move across my jFrame. This Dot would only be able to move on a picture of a grid in my jFrame upon keystroke. If anyone can post some code (as example for me to refer to) as to how to create the "dot/point" and how to make this dot move across my jFrame on keystroke i would greatly appreciate it. thanks :)
Once you have a JFrame, you need to add a JPanel to it and put your rendering code in the repaint() method of the JPanel.
I would suggest you look at this example of how to use a JFrame properly.
public class MyJFrame extends JFrame implements KeyListener {
private MyJPanel frame;
public MyJFrame() {
super();
frame = new MyJPanel();
add(frame);
pack();
addKeyListener(this);
repaint();
}
public static void main(String[] args) {
MyJFrame window = new MyJFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.setTitle("Test");
}
#Override
public void repaint() {
super.repaint();
}
#Override
public void keyPressed(KeyEvent e) {
frame.keyPressed(e);
repaint();
}
#Override
public void keyTyped(KeyEvent e) { }
#Override
public void keyReleased(KeyEvent e) { }
}
Here is the MyJPanel class:
public class MyJPanel extends JPanel {
private int x = 0;
private int y = 0;
public MyJPanel() {
setPreferredSize(new Dimension(200,200));
}
#Override
public void update(Graphics g) {
paint(g);
}
#Override
public void paint(Graphics g) {
g.setColor(Color.red);
g.drawRect(x,y,1,1);
}
public void keyPressed(KeyEvent e) {
int k = e.getKeyCode();
switch (k) {
case KeyEvent.VK_D:
x++;
break;
case KeyEvent.VK_A:
x--;
break;
case KeyEvent.VK_W:
y--;
break;
case KeyEvent.VK_S:
y++;
break;
}
}
}
Using KeyListener is optional but allows you to get keyboard input.
I know that this is long and not very direct, but I hope you can learn something from this code. If you have any other questions, feel free to comment, and I'll help you out as best I can.
MyJFrame needs to import:
java.awt.event.KeyEvent;
java.awt.event.KeyListener;
javax.swing.JFrame;
MyJPanel needs to import:
java.awt.Color;
java.awt.Dimension;
java.awt.Graphics;
java.awt.event.KeyEvent;
javax.swing.JPanel;

why does the int not change? java

Can someone please tell me how i can get the value of int x in my following code:
when i move the square left and right, the output from Test stays as 500.
I am wanting the Thread in Test to get the value of x every time it loops, but x is always 500 (from the thread) even though the value of x is changing in Drawing.java. please help me with this.
package block;
public class Test extends Drawing implements Runnable{
Thread collision = new Thread(this);
public Test() {
collision.start();
}
#Override
public void run() {
while(true) {
System.out.println(x);
}
}
}
package block;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Drawing extends Canvas implements Runnable, KeyListener{
Thread thread = new Thread(this);
int x = 500;
int y = 540;
public Drawing() {
setSize(1000, 800);
addKeyListener(this);
thread.start();
}
public void update(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, 1000, 700);
paint(g);
}
public void paint(Graphics g) {
g.setColor(Color.cyan);
g.fillRect(x, y, 50, 50);
}
#Override
public void run() {
while(true) {
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(Drawing.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
#Override
public void keyTyped(KeyEvent ke) {
}
#Override
public void keyPressed(KeyEvent ke) {
if(ke.getKeyCode() == KeyEvent.VK_LEFT) {
x -= 5;
}
if(ke.getKeyCode() == KeyEvent.VK_RIGHT) {
x += 5;
}
}
#Override
public void keyReleased(KeyEvent ke) {
}
}
EDIT: --------------------
package block;
import javax.swing.JFrame;
public class Block extends JFrame{
Test test = new Test();
public Block() {
setSize(1000, 700);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
add(new Drawing());
setVisible(true);
createBufferStrategy(2);
}
public static void main(String[] args) {
new Block();
}
}
You are creating multiple instances of x because you are not using inheritance correctly. When you call new Test(), that creates one instance of a Test (which contains a Drawing, which contains a member x), and then the call to new Drawing() creates another instance of a Drawing (which contains a different member x).
To fix this, you could pass a reference to a Drawing object to your Test constructor, and access the x member through the reference.

Why wont my Java program acknowledge any key strokes using KeyListener?

I have literally no idea why my program isn't recognizing keyboard input. I have places print statements throughout the program to determine the issue, and I have determined that the keyPressed method never activates. This is for a game which I am making for a class project, and yes I am a relatively beginner programmer. Thanks in advance! (Code below)
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
public class Dodger extends JApplet implements Runnable, KeyListener {
Thread myThread;
public Image bg;
public Image pic;
public boolean loaded;
public int cx, cy, speed, x, y;
public void init(){
setSize(800,800);
loaded = false;
x = 2;
y = 400;
cx = 0;
cy = 0;
speed = 3;
myThread = new Thread(this);
myThread.start();
addKeyListener(this);
}
public void run(){
loadpic();
repaint();
while (myThread!=null)
{
try{
myThread.sleep(18);
}catch(InterruptedException e){
e.printStackTrace();
}
repaint();
}
}
public void upMotion(){
cy = cy + speed;
}
public void downMotion(){
cy = cy - speed;
}
public void leftMotion(){
cx = cx - speed;
}
public void rightMotion(){
cx = cx + speed;
}
#Override
public void keyPressed(KeyEvent k) {
if (k.getKeyCode() == KeyEvent.VK_LEFT) {
System.out.println("work");
leftMotion();
}
if (k.getKeyCode() == KeyEvent.VK_RIGHT) {
rightMotion();
}
if (k.getKeyCode() == KeyEvent.VK_UP) {
upMotion();
}
if (k.getKeyCode() == KeyEvent.VK_DOWN) {
downMotion();
}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
public void loadpic(){
bg = new ImageIcon(getClass().getResource("back.png")).getImage();
pic = new ImageIcon(getClass().getResource("smile.png")).getImage();
loaded = true;
repaint();
}
public void paint(Graphics g){
g.drawImage(bg, 0, 0, this);
g.drawImage(pic, cx, cy, this);
}
}
The key events are detected just fine when the applet is focusable & has focus. Managing focus has always been a problem with applets. The problem is mostly that Sun never bothered to specify the focus behavior that should ideally apply to a mixed page of focusable HTML elements and applet(s).
As per Tom's advice, add to the end of init()
setFocusable(true);
To be safe, also override:
public void start() {
this.requestFocusInWindow();
}
As an aside, generally it is better to use key bindings in Swing. They also require the applet to have input focus.
First off, you probably want to separate out your class from your KeyListener, as it makes it a bit harder to read.
Next, you want to get rid of the bare Thread and wrap it in a timer.
import javax.swing.Timer;
class Dodger extends JApplet {
Timer imageUpdater; //replaces Thread
/*...*/
public void init() {
/*etc*/
loadpic();
int repaintInterval = 100;
imageUpdater = new Timer(repaintInterval,
new ActionListener() {
public void actionPerformed(ActionEvent e) {
repaint();
}
}
);
imageUpdater.start();
addKeyListener(new KeyHandler());
setFocusable(true);
}
/*...*/
private class KeyHandler extends KeyAdapter {
/* Note that with this implementation, you do not have to override
* unnecessary methods, as KeyAdapter is an abstract class that
* implements all of the methods of KeyListener.
*/
#Override
public void keyPressed(KeyEvent e) {
/*...*/
}
}
/*...*/
}
Most of this is just code cleanup - the actual problem may be fixed (according to Tom, see comments) with the setFocusable(true).
I'm not really sure if it applies to Applets, but your Thread may not allowing the event dispatching to occur.
Try to run your "work" with SwingWorker.

Categories