Go Back   CodingForums.com > :: Server side development > Java and JSP

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 05-18-2010, 02:05 AM   PM User | #1
Alice.B
New to the CF scene

 
Join Date: May 2010
Posts: 2
Thanks: 1
Thanked 0 Times in 0 Posts
Alice.B is an unknown quantity at this point
Help with Key Events and JPanel Animation

Hello! I have been working on a game where the objective will eventually be to avoid randomly generated side-scrolling blocks with a user-controlled piece, as of now only controlled by buttons. I have a few questions though.

I have looked in many tutorials and places online, but I can't seem to get key events to work. I want to have the option of controlling the player with a key event or the buttons that already exist. If someone could just give me an example of how I could implement this in my code it would be great.

My second question is about how to create animation in a JPanel, specifically side-scrolling boxes. Where should I put the code? I think I understand the logic that I would use, I'm just unsure of the specifics. A friend said that a timer object is an easy way to do this but I've never used one. Would you agree?

If someone could help me out with any of this I would be really grateful.


Here is the panel code:
Code:
package BlockGame;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Random;


public class BlockGamePanel extends JPanel implements ActionListener, KeyListener
{

    Random generator = new Random();
    final int INITIALX=300;
    final int INITIALY=150;
    JButton right, left, up, down;
    int x=50, y=50;

    public BlockGamePanel(int width, int height)

    {
        left = new JButton ("left");
        add(left);
        left.addActionListener(this);
        
        right = new JButton("right"); 
        add (right); 
        right.addActionListener(this); 

        up = new JButton ("up");
        add (up);
        up.addActionListener(this);

        down = new JButton ("down");
        add (down);
        down.addActionListener(this);

    }
    
 public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(Color.red);
        g.fillRect (x,y,15,15);

        repaint();
    }

 //move the player piece around
     public void actionPerformed (ActionEvent event)
    {
        if (event.getSource() == right) 
            x+=15;

        if (event.getSource() == left)
            x-=15;

        if (event.getSource() == up)
            y-=15;

        if (event.getSource() == down)
            y+=15;

        repaint();
    }

    public void keyTyped(KeyEvent e) {

    }

    public void keyPressed(KeyEvent e) {

    }


    public void keyReleased(KeyEvent e) {

    }


}

And, just in case, this is the run class.
Code:
package BlockGame;

import java.awt.*;
import javax.swing.*;

public class BlockGame {

    public static void main(String[] args)
    {
    JFrame frame = new JFrame ("BlockGame");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setPreferredSize(new Dimension(400,400));
    frame.getContentPane().add(new BlockGamePanel(400,400));

    frame.pack();
    frame.setVisible(true);
    }
}
Alice.B is offline   Reply With Quote
Old 05-19-2010, 06:51 PM   PM User | #2
TheShaner
Senior Coder

 
TheShaner's Avatar
 
Join Date: Sep 2005
Location: Orlando, FL
Posts: 1,125
Thanks: 2
Thanked 40 Times in 40 Posts
TheShaner will become famous soon enoughTheShaner will become famous soon enough
I don't know anything about animation in Java unfortunately; maybe look at these samples -> http://java.sun.com/products/java-me...samples/suite/

This is a great Key Listener tutorial, mainly because running the actual program gives you a lot of insight on how key events work. Play with it and you'll see.

For you, you'll need to addKeyListener to your JPanel. Then, in your keyPressed method, you'll have to check which key event is coming in. For example:
Code:
switch(e.getKeyCode())
{
    case 40: // Down
        y += 15;
    // and so on...
}
The key codes you are probably interested in:
Code:
Down: 40
Up: 38
Left: 37
Right: 39
Running the demo I linked you to will enable you to get all the key codes. Also, you can do KeyEvent.getKeyText(e.getKeyCode()), which will print the string name of the key you've pressed, i.e. "Right".

I actually recommend creating a separate class that will hold your "player" that will be moving around in your environment. You would then call move commands on the instance of your player as keys or buttons are pressed. You'll repaint the object every time you move it.

-Shane
TheShaner is offline   Reply With Quote
Users who have thanked TheShaner for this post:
Alice.B (05-27-2010)
Old 05-27-2010, 02:41 AM   PM User | #3
Alice.B
New to the CF scene

 
Join Date: May 2010
Posts: 2
Thanks: 1
Thanked 0 Times in 0 Posts
Alice.B is an unknown quantity at this point
Thank you very much for your help, TheShaner. My program is now compiling and working well. I have modified the original slightly, in order to scroll circles to the right. I still need to create a separate Player class as per your suggestion, but I don't foresee many issues with that. I am having a slight problem with my logic though. I want to iterate through the 'for' loop going one at a time, with a slight delay between each. Unfortunately right now all the circle objects seem to fire off at once. I'm sure there's simply something I'm doing wrong, and if anyone could help out that would be wonderful. Here is my current code:

Code:
//****************************************
//  NOTE:
//  It would be wise to create a class called player that does all of the controlling,
//  rather than having it in the panel class.

package BlockGame;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Random;


/**
 *
 * @author alibresnah10
 */
public class BlockGamePanel extends JPanel implements 
                                                        KeyListener,
                                                            FocusListener,
                                                                MouseListener
{

    Random generator = new Random();
    final int WH=300;
    final int AWIDTH, AHEIGHT;
    Timer timer;
    private int arraySize =8;
    private int squareTop=200, squareLeft=200;
    int moveX, moveY;
    private static final int SQUARE_SIZE = 20;


    Circle[] carray = new Circle[8];


    public BlockGamePanel(int width, int height)

    {
        timer = new Timer(20, new ReboundListener());
        moveX=moveY=generator.nextInt(15);
        for (int i = 0; i < arraySize; i++)
        {
           carray[i]=new Circle();
        }
       
         AWIDTH=width;
         AHEIGHT=height;

         setBackground(Color.WHITE);

         addKeyListener(this);     // Set up event listening.
         addFocusListener(this);
         addMouseListener(this);



    }
 public void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        //change the color for if the panel has focus... needed for keyevents
         if (hasFocus())
              g.setColor(Color.RED);
         else
            g.setColor(Color.LIGHT_GRAY);

        //draw a border that shows whether the panel has focus.
         int width = getSize().width;  // Width of the applet.
         int height = getSize().height; // Height of the applet.
         g.drawRect(0,0,width-1,height-1);
         g.drawRect(1,1,width-3,height-3);
         g.drawRect(2,2,width-5,height-5);



         //draw the player piece, controllable by keyboard.
         g.fillRect(squareLeft, squareTop, SQUARE_SIZE, SQUARE_SIZE);



         for (int i=0; i<carray.length; i++)
         {
             carray[i].draw(g);
         }



         if (hasFocus()) {
            g.drawString("Arrow Keys Move Player",7,20);
         }
         else
         {
            g.drawString("Click to activate",7,20);
            g.setColor(Color.cyan);
         }
         g.setColor(Color.green);


        repaint();
    }

    public void keyPressed(KeyEvent ke)
    {
        int key = ke.getKeyCode();  // keyboard code for the pressed key

         if (key == KeyEvent.VK_LEFT) {
            squareLeft -= 8;
            if (squareLeft < 3)
               squareLeft = 3;
            repaint();
         }
         else if (key == KeyEvent.VK_RIGHT) {
            squareLeft += 8;
            if (squareLeft > getWidth() - 3 - SQUARE_SIZE)
               squareLeft = getWidth() - 3 - SQUARE_SIZE;
            repaint();
         }
         else if (key == KeyEvent.VK_UP) {
            squareTop -= 8;
            if (squareTop < 3)
               squareTop = 3;
            repaint();
         }
         else if (key == KeyEvent.VK_DOWN) {
            squareTop += 8;
            if (squareTop > getHeight() - 3 - SQUARE_SIZE)
               squareTop = getHeight() - 3 - SQUARE_SIZE;
            repaint();
        }
    }



    public void focusGained(FocusEvent e)
    {
        repaint();
    }

    public void focusLost(FocusEvent e)
    {
        repaint();
    }

    public void mouseClicked(MouseEvent e) {
        requestFocus();
        timer.start();
    }
 //provide empty definitions
    public void keyTyped(KeyEvent e) { }
    public void keyReleased(KeyEvent e) {    }
    public void mousePressed(MouseEvent e) {    }
    public void mouseReleased(MouseEvent e) {    }
    public void mouseEntered(MouseEvent e) {    }
    public void mouseExited(MouseEvent e) {    }


    public class ReboundListener implements ActionListener
    {
        public void actionPerformed(ActionEvent action)
        {

            for (int i = 0; i < carray.length; i++)
            {
	    carray[i].move(moveX);


	    if (carray[i].getX() < 0 || carray[i].getX() >= AWIDTH - carray[i].getRadius())
            {
                carray[i].setX(0);
                carray[i].setY(generator.nextInt(AHEIGHT));
            }


	    repaint();
            }
        }
	// ----------------------------------------------------
	// actionPerformed is called by the timer -- it updates
	// the position
	// ----------------------------------------------------

    }
}
And here is my 'circle' class, the one whose objects I am firing off using the timer.

Code:
import java.awt.*;
import java.util.Random;

public class Circle
{
    private int x, y;       // coordinates of the corner
    private int radius;     // radius of the circle
    private Color color;    // color of the circle
    private int width, height =300;

    static Random generator = new Random();


    public Circle()
    {
        radius = Math.abs(generator.nextInt(20)+5);

        x = 1;//modify for original plan... scrolling to the left.
        y = Math.abs(generator.nextInt(300));
    }

    //----------------------------------------------------------
    // Creates a circle of a given size (diameter).  Other
    // attributes are random (as described above)
    //---------------------------------------------------------
    public Circle(int size)
    {
        radius = Math.abs(size/2);
        color = new Color(Math.abs(generator.nextInt())% 16777216);
        x = 0;
        y = Math.abs(generator.nextInt())%400;
    }


    //---------------------------------------------------------
    // Draws circle on graphics object given
    //---------------------------------------------------------
    public void draw(Graphics page)
    {
        page.setColor(color);
        page.fillOval(x,y,radius*2,radius*2);
    }


    //--------------------------------------------------------
    // Shifts the circle's position 
    //--------------------------------------------------------
    public void move (int over)
    {
        x = x + over;
        //y = down;
    }

    // ---------------------------------------------
    // Return the x coordinate of the circle corner
    // ---------------------------------------------
    public int getX()
    {
        return x;
    }

    public int setX(int set)
    {
        x=set;
        return x;
    }
    public int setY(int set)
    {
        y=set;
        return y;
    }
    // ---------------------------------------------
    // Return the y coordinate of the circle corner
    // ---------------------------------------------
    public int getY()
    {
        return y;
    }
    public int getRadius()
    {
        return radius;
    }
}
Alice.B is offline   Reply With Quote
Old 06-01-2010, 03:49 PM   PM User | #4
TheShaner
Senior Coder

 
TheShaner's Avatar
 
Join Date: Sep 2005
Location: Orlando, FL
Posts: 1,125
Thanks: 2
Thanked 40 Times in 40 Posts
TheShaner will become famous soon enoughTheShaner will become famous soon enough
Well, it all depends on what you're attempting to do. The way you have it set up, you have a timer that calls it's Action Listener's actionPerformed method every 20ms. In that actionPerformed method, you loop through the array of 8 Circles to change their locations. That means, every 20ms, all 8 circles move virtually at once!

What do you really want to happen? Do you want only 1 Circle moved every 20ms? You said you want a delay in between, so use the timer to execute this delay. Instead of looping through all 8 Circles, only perform a move on 1 Circle at time, using your Timer to do the delay between moving them.

In your ReboundListener class, add a private variable that stores which Circle you want to move next (let's call it circleToMove) and initialize it with 0. Then, completely ditch the for loop in your ReboundListener class and just do a move on carray[circleToMove]. After you perform the move, increment circleToMove by 1 so that when the timer executes 20ms later, it'll move the next Circle in your array. You'll also have to do a check to see if circleToMove is greater than 7 after you increment, because if so, you'll want to go back to 0.

-Shane
TheShaner is offline   Reply With Quote
Reply

Bookmarks

Tags
animation, game, jpanel, key events, timer

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 09:10 AM.


Advertisement
Log in to turn off these ads.