java KeyListener not responding? - java

I have this code the green square is meant to move but it doesn't I have done everything right. its just the key listen doesn't seem to be responding. I think there's a error around
addKeyListener(this); in the paintComponent in my Graphics class can you please help and tell me how to fix it and what's wrong.
my Main class
import javax.swing.JFrame;
public class Main {
static int v = 50;
static int t = 1;
public static void main(String[] args) {
JFrame frame = new JFrame("window");
frame.setVisible(true);
frame.setSize(400,200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Graphics object = new Graphics();
frame.add(object);
while (v > t){
object.Drawing();
}
}
}
my Graphics class
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class Graphics extends JPanel implements KeyListener {
int x = 0, y= 0, xx = 100, yy = 0, ltyx = 0, ltyyxx = 0, px = 0, py = 0;
public void Drawing(){
repaint();
}
public void paintComponent (java.awt.Graphics g){
super.paintComponent (g);
addKeyListener(this);
setBackground(Color.WHITE);
g.setColor(Color.GREEN);
g.fillRect(px, py, 25, 25);
g.setColor(Color.BLUE);
g.fillRect(x, y, 50, 50);
g.setColor(Color.RED);
g.fillRect(xx, yy, 50, 50);
g.drawString("times looped around screen Blue : " + ltyx , 10, 10);
g.drawString("Red : " + ltyyxx , 170, 20);
x++;
xx++;
if (x > 400){
x = 0;
y += 50;
}
if (xx > 400){
xx = 0;
yy += 50;
}
if (y > 200){
y = 0;
ltyx++;
}
if (yy > 200){
yy = 0;
ltyyxx++;
}
}
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_RIGHT:{
px++;
break;
}
case KeyEvent.VK_LEFT:{
px--;
break;
}
case KeyEvent.VK_UP:{
py++;
break;
}
case KeyEvent.VK_DOWN:{
py--;
break;
}
}
}
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_RIGHT:{
px = 0;
break;
}
case KeyEvent.VK_LEFT:{
px = 0;
break;
}
case KeyEvent.VK_UP:{
py = 0;
break;
}
case KeyEvent.VK_DOWN:{
py = 0;
break;
}
}
}
public void keyTyped(KeyEvent e) {
}
}

In user interfaces there is the concept of 'focus'. Only the component currently holding the focus directly receives key events. This is how for example, when typing, one text box on screen responds and not any other.
After frame.add(object);, add:
object.setFocusable(true);
object.requestFocusInWindow();
Also, the addKeyListener(this); call is in quite the wrong place. It will add another key listener every time it paints the component. It should be called only once, ideally in the constructor of the panel.

Related

How to add an extra control point to a Bezier curve?

Here is the code which creates the bezier curve with total 4 control points:
Blue color is the starting and end control point.
Cyan color is the second and third control point.
I want to add a control point to the existing curve so that now I have 3 cyan coloured control points so that I can resize the curve(like dragging the curve) from any of these 3 control points instead of the 2 control points. What needs to be done for this?
I have attached the output of the below code as an attachment.
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.GeneralPath;
public class Piyush extends Frame implements MouseListener, MouseMotionListener {
// private int[] xs = { 75, 150, 300, 375 };
//
// private int[] ys = { 250, 100, 350, 250 };
private int[] xs = { 75, 200, 300, 375 };
private int[] ys = { 250, 100, 100, 250 };
private int dragIndex = NOT_DRAGGING;
private final static int NEIGHBORHOOD = 15;
private final static int NOT_DRAGGING = -1;
public static void main(String[] args) {
new Piyush();
}
public Piyush() {
setSize(500, 450);
addMouseListener(this);
addMouseMotionListener(this);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setVisible(true);
}
public void paint(Graphics g) {
for (int i = 0; i < 4; i++) {
if (i == 0 || i == 3){
g.setColor(Color.blue);
g.fillOval(xs[i] - 6, ys[i] - 6, 12, 12);}
else{
g.setColor(Color.cyan);
g.fillOval(xs[i] - 6, ys[i] - 6, 12, 12);
}
}
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.black);
GeneralPath path = new GeneralPath();
path.moveTo(xs[0], ys[0]);
path.curveTo(xs[1], ys[1], xs[2], ys[2], xs[3], ys[3]);
g2d.draw(path);
}
public void mousePressed(MouseEvent e) {
dragIndex = NOT_DRAGGING;
int minDistance = Integer.MAX_VALUE;
int indexOfClosestPoint = -1;
for (int i = 0; i < 4; i++) {
int deltaX = xs[i] - e.getX();
int deltaY = ys[i] - e.getY();
int distance = (int) (Math.sqrt(deltaX * deltaX + deltaY * deltaY));
if (distance < minDistance) {
minDistance = distance;
indexOfClosestPoint = i;
}
}
if (minDistance > NEIGHBORHOOD)
return;
dragIndex = indexOfClosestPoint;
}
public void mouseReleased(MouseEvent e) {
if (dragIndex == NOT_DRAGGING)
return;
xs[dragIndex] = e.getX();
ys[dragIndex] = e.getY();
dragIndex = NOT_DRAGGING;
repaint();
}
public void mouseDragged(MouseEvent e) {
if (dragIndex == NOT_DRAGGING)
return;
xs[dragIndex] = e.getX();
ys[dragIndex] = e.getY();
repaint();
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
}
Also asked here
http://www.dreamincode.net/forums/topic/408270-need-help-in-adding-a-control-point-for-bezier-curve/page__pid__2347742__st__0&#entry2347742
code base comes from here
http://www.java2s.com/Tutorials/Java/Graphics/Shape/Drag_the_control_point_for_Bezier_curve_in_Java.htm

For loop(s) not working as intended with graphics

I've been trying to make a for loop that horizontally replicates vertical lines across the screen, each the same distance apart from its precedent; however, my code doesn't seem to work despite appearing to be syntactically correct. I've posted my code below, hopefully someone can identify the problem.
class HVLines
{
public static void Lines(Graphics g)
{
int k;
int x=0;
for (k = 1; k <= 50; k++)
{
g.drawLine(20+x,150,20+x,525);
for (x = 1; x <= 50; x+=20)
{
}
}
}
}
It should look like this. I can't ensure it will work since I don't know how you use it. Also, in your loops, you use x twice, but don't use k. Change one of those, or , if you don't need it, erase one of the loops.
I am prett sure this one creates a diagonal line, not horizontal.
for (k = 1; k <= 50; k++) {
for (x = 1; x <= 50; x+=20) {
// Choose one of the following
g.drawLine(20+k,150,20+x,525);
g.drawLine(20+x,150,20+k,525);
}
}
This one creates a straight line:
for (x = 1; x <= 50; x+=20) {
g.drawLine(20+x,150,20+x,525);
}
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import javax.swing.JApplet;
import javax.swing.JFrame;
public class DrawLine extends JApplet {
public void init() {
setBackground(Color.white);
setForeground(Color.white);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(Color.gray);
for (int y = 0; y <= 300; y += 30) {
g2.draw(new Line2D.Double(0, y, 300, y));
}
}
public static void main(String s[]) {
JFrame f = new JFrame("Line");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JApplet applet = new DrawLine();
f.getContentPane().add("Center", applet);
applet.init();
f.pack();
f.setSize(new Dimension(300, 300));
f.setVisible(true);
}
}

How can I get this Paintcomponent to act as I intended?

I was given the assignment to make a simple paint program in java that utilizes a GUI and has basic I/O capabilities. That was all I was told to do by my professor. However, I've only made one GUI program before, so jumping straight into this paint program has been a headache. Now I'm nearly done, but the program isn't really behaving as I expected. When new objects are drawn on the Panel, they draw invisible white rectangles on the objects underneath them that erases those objects. I think this is the result of the repaint(xMin, yMin, xMax - xMin + 1, yMax - yMin + 1); method in DrawShapes, but can't think of a way to fix it.
On the other hand, the objects are also not saving properly. I can get it to export a jpg as I intended, however, it will only export the last image drawn and not everything on the paintComponent canvas.
Lastly, the clear method in DrawShapes is working in a very similar way. When the clear method is activated, it will clear everything but the last image drawn.
Is there anyone more familiar than me with these tools that can see a way to fix these? This is only the first program I've utilized draw on, and I/O.
Here is the class for the panel that the shapes are supposed to drawn on:
/**
* #author me
*/
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class DrawShapes extends JPanel{
Point startPoint = null;
Point endPoint = null;
public int drawType = 1;
BufferedImage image;
Graphics2D g2d;
public DrawShapes(){
setBackground(Color.WHITE);
MyMouseListener m1 = new MyMouseListener();
addMouseListener(m1);
addMouseMotionListener(m1);
}//end constructor
//sets draw type, which is the decider of what is being drawn.
public void setType(int type){
if(type == 1)
{
drawType = 1;
}
else if(type == 2)
{
drawType = 2;
}
else if(type == 3)
{
drawType = 3;
}
}//end setType
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if (image == null)
{
createEmptyImage();
}
g.drawImage(image, 0, 0, null);
if (startPoint != null && endPoint != null)
{
int x = Math.min(startPoint.x, endPoint.x);
int y = Math.min(startPoint.y, endPoint.y);
int width = Math.abs(startPoint.x - endPoint.x);
int height = Math.abs(startPoint.y - endPoint.y);
switch (drawType)
{
case 1:
g.drawRect(x, y, width, height);
break;
case 2:
g.drawOval(x, y, width, height);
break;
case 3:
g.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
break;
}
}
}//end paintComponent
public void save()
{
BufferedImage bi = new BufferedImage(this.getSize().width, this.getSize().height, BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
this.paint(g);
g.dispose();
try{ImageIO.write(bi, "png",new File("test.png"));
}catch (Exception e){}
}
private void createEmptyImage()
{
image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
g2d = (Graphics2D)image.getGraphics();
g2d.setColor(Color.BLACK);
g2d.drawString("Add a shape by clicking and dragging.", 40, 15);
}
public void addRect(int x, int y, int width, int height, Color color)
{
g2d.setColor( color );
g2d.drawRect(x, y, width, height);
repaint();
}
public void addOval(int x, int y, int width, int height, Color color)
{
g2d.setColor( color );
g2d.drawOval(x, y, width, height);
repaint();
}
public void addLine(int x1, int y1, int x2, int y2, Color color)
{
g2d.setColor(color);
g2d.drawLine(x1, y1, x2, y2);
repaint();
}
public void clear()
{
createEmptyImage();
repaint();
}
class MyMouseListener extends MouseInputAdapter
{
private int xMin;
private int xMax;
private int yMin;
private int yMax;
public void mousePressed(MouseEvent e)
{
startPoint = e.getPoint();
endPoint = startPoint;
xMin = startPoint.x;
xMax = startPoint.x;
yMin = startPoint.y;
yMax = startPoint.y;
}
public void mouseDragged(MouseEvent e)
{
//This is code I found that should make it so the only area affected by the dragging is repainted.
endPoint = e.getPoint();
xMin = Math.min(xMin, endPoint.x);
xMax = Math.max(xMax, endPoint.x);
yMin = Math.min(yMin, endPoint.y);
yMax = Math.max(yMax, endPoint.y);
repaint(xMin, yMin, xMax - xMin + 1, yMax - yMin + 1);
}
public void mouseRelease(MouseEvent e)
{
//This code paints the shapes on the Buffered Image created as a canvas
int x = Math.min(startPoint.x, endPoint.x);
int y = Math.min(startPoint.y, endPoint.y);
int width = Math.abs(startPoint.x - endPoint.x);
int height = Math.abs(startPoint.y - endPoint.y);
if (width != 0 || height != 0)
{
g2d.setColor( e.getComponent().getForeground() );
// g2d.drawRect(x, y, width, height);
switch (drawType)
{
case 1:
addRect(x, y, width, height, e.getComponent().getForeground());
break;
case 2:
addOval(x, y, width, height, e.getComponent().getForeground());
break;
case 3:
addLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, e.getComponent().getForeground());
break;
}//end switch statement.
}
startPoint = null;
// repaint();
}
}
}//end class
And here is the code for the UI:
/*#author Me*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MyDrawUI extends JFrame
{
private DrawShapes draw = new DrawShapes();
private JPanel ButtonPanel = new JPanel();
private JFrame window = new JFrame("Draw!");
//constructor
MyDrawUI(){
buildUI();
}
void buildUI()
{
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLayout(new GridLayout(2,2));
window.add(draw);
window.add(ButtonPanel, BorderLayout.SOUTH);
ButtonPanel.setBackground(Color.LIGHT_GRAY);
draw.setBackground(Color.WHITE);
//define buttons
JButton rectangle = new JButton("Rectangle");
JButton oval = new JButton("Oval");
JButton line = new JButton("Line");
JButton exit = new JButton("Exit");
JButton save = new JButton("Save");
JButton clear = new JButton("Clear");
//add buttons
ButtonPanel.add(rectangle, BorderLayout.SOUTH);
ButtonPanel.add(oval, BorderLayout.SOUTH);
ButtonPanel.add(line, BorderLayout.SOUTH);
ButtonPanel.add(clear, BorderLayout.SOUTH);
ButtonPanel.add(save, BorderLayout.SOUTH);
ButtonPanel.add(exit, BorderLayout.SOUTH);
ButtonPanel.setSize(100, 100);
save.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
draw.save();
}
});
clear.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
draw.clear();
}
});
rectangle.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
draw.setType(1);
}
});
oval.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
draw.setType(2);
}
});
line.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
draw.setType(3);
}
});
exit.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
window.setVisible(true);
window.setSize(1024, 800);
}
}
There are a few issues I can see, the main one is the fact that you "think" you've overridden a method in the MouseAdaptor class, but haven't
mouseRelease is not method that will cause any events to trigger it. The method you're after is mouseReleased.
When overriding methods, make use the #Override annotation, it will cause a compiler error if the method you "think" you're overriding doesn't exist in any of the parent classes.
#Override
public void mouseReleased(MouseEvent e) {
Several other things pop out.
You're MyDrawUI classes extends from JFrame, but you create a instance of another JFrame called window, onto which you create your UI. In this case, drop the extends JFrame from the MyDrawUI class, as it just adds confusion...
Maintaining a reference to a Graphics context, even one you created, is ill advised in this context. On some systems, until you call dispose it's possible that nothing will be committed to the underlying implementation. Instead, simply use image.getGraphics when you need it and call g2d.dispose when you're done with it.

mouse motion listener only in one direction

i have been working on mouse motion listener in Java couldn't sort it out completely because i want the object to move towards the direction where ever on the screen the mouse is pointed at but unforunately when the mouse is inside the applet window, the object moves only towards a single direction. Here is my code below..
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import java.applet.*;
import java.awt.event.*;
import javax.swing.*;
public class MouseOver extends Applet implements KeyListener, MouseListener,
MouseMotionListener {
private int[] Xpoints = { 0, -5, 5 };
private int[] Ypoints = { -10, -2, -2 };
private double xpos, ypos;
private Polygon poly;
int polyrot = 0;
private int width; // !! added
private int height; // !! added
public void init() {
poly = new Polygon(Xpoints, Ypoints, Xpoints.length);
addKeyListener(this);
addMouseListener(this);
addMouseMotionListener(this);
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform id = new AffineTransform();
width = getSize().width;
height = getSize().height;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, width, height);
g2d.setColor(Color.RED);
g2d.draw(poly);
g2d.translate(width / 2, height / 2);
g2d.rotate(Math.toRadians(polyrot));
g2d.scale(5, 5);
}
public void keyReleased(KeyEvent k) {
}
public void keyTyped(KeyEvent k) {
}
public void keyPressed(KeyEvent k) {
switch (k.getKeyCode()) {
case KeyEvent.VK_LEFT:
if (polyrot < 0) {
polyrot = 359;
polyrot++;
}
repaint();
break;
case KeyEvent.VK_RIGHT:
if (polyrot > 360) {
polyrot = 0;
polyrot--;
}
repaint();
break;
}
}
public void mouseEntered(MouseEvent m) {
}
public void mouseExited(MouseEvent m) {
}
public void mouseReleased(MouseEvent m) {
}
public void mouseClicked(MouseEvent m) {
}
public void mousePressed(MouseEvent m) {
switch (m.getButton()) {
case MouseEvent.BUTTON1:
if (polyrot < 0) {
polyrot = 359;
polyrot--;
}
repaint();
break;
case MouseEvent.BUTTON2:
if (polyrot > 360) {
polyrot = 0;
polyrot++;
}
repaint();
break;
}
}
public void mouseMoved(MouseEvent e) {
xpos = getX();
if (xpos < 0) {
polyrot--;
} else if (xpos > 0) {
polyrot++;
}
repaint();
// !! break; // Doesn't belong here
}
#Override
public void mouseDragged(MouseEvent e) {
// You forgot this method
}
}
Your problem is with this line:
public void mouseMoved(MouseEvent e){
xpos=getX(); // ******
if(xpos<0){polyrot--;}
else if(xpos>0){polyrot++;}
repaint();
break;
}
That returns the x position of the applet not the mouse cursor. You need to use your MouseEvent object, e and instead get the mouse's position. Change it to:
xpos = e.getX();
Please don't ignore the comment that I made to your question. Please remember that we're volunteers who help on our free time. Please don't make it any more difficult than it has to be to help you.
I've tried to edit your code so that it compiles, and now is indented. Consider creating a Swing application, not an AWT application, since Swing apps are more flexible, powerful and robust.
This:
if (xpos < 0) {
means "if the cursor is outside of the panel".
This:
xpos = getX();
does not get a mouse coordinate.
Change your event to something like this:
public void mouseMoved(MouseEvent e) {
xpos = e.getX();
if (xpos < getWidth() / 2) {
polyrot--;
} else {
polyrot++;
}
repaint();
}
Now it rotates counter-clockwise if the cursor is on the left side of the panel and clockwise if the cursor is on the right side.
This:
g2d.draw(poly);
g2d.translate(width / 2, height / 2);
g2d.rotate(Math.toRadians(polyrot));
g2d.scale(5, 5);
will not do anything to change the image because you are doing your transforming after drawing it.
This:
Graphics2D g2d = (Graphics2D) g;
is a bad idea because you are applying transforms to the global graphics context which would carry on to subsequent repaints of other components.
Change your paint to something like this:
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g.create();
width = getSize().width;
height = getSize().height;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, width, height);
g2d.translate(width / 2, height / 2);
g2d.rotate(Math.toRadians(polyrot));
g2d.scale(5, 5);
g2d.setColor(Color.RED);
g2d.draw(poly);
g2d.dispose();
}
Further reading:
Painting in AWT and Swing
How to Write a Mouse Listener
There are a few things...
In your keyPressed and mousePressed events, are are only ever process the out of bounds conditions, for example...
if (polyrot < 0) {
polyrot = 359;
polyrot++;
}
//...
if (polyrot > 360) {
polyrot = 0;
polyrot--;
}
But you never process what it should do when it's within the acceptable bounds (0-359)...
Instead, you could simply add or subtract the amount from polyrot and allow the API to deal with it (surprisingly, it's capable for dealing with angles < 0 and > 359), for example...
public void mousePressed(MouseEvent m) {
switch (m.getButton()) {
case MouseEvent.BUTTON1:
polyrot--;
repaint();
break;
case MouseEvent.BUTTON2:
polyrot++;
repaint();
break;
}
}
Now, I'm not sure what you mean by "object to move towards the direction where ever on the screen the mouse is pointed". Does this mean that the object should actually change it's x/y coordinates or should it just "look" at the mouse cursor...
Based on the fact that you actually have no movement code and you basically have the object painted in a fixed location, I'm assuming "look at"...
Basically, you need to know where the mouse is and where the object is, then determine the angle between them...
public void mouseMoved(MouseEvent e) {
int x = width / 2;
int y = height / 2;
Point mousePoint = e.getPoint();
int deltaX = mousePoint.x - x;
int deltaY = mousePoint.y - y;
polyrot = -Math.atan2(deltaX, deltaY);
polyrot = Math.toDegrees(polyrot) + 180;
repaint();
}
You should note that I changed 'polyrot' to 'double'
Your paint method is also wrong. Basically, you are painting your object BEFORE you've transformed it, instead, you should be using something more like...
g2d.translate(width / 2, height / 2);
g2d.rotate(Math.toRadians(polyrot));
g2d.draw(poly);
You should also be calling super.paint(g) before you apply you own custom painting...
As a side note, you should avoid overriding paint of top level containers, like JApplet, but instead, create a custom component, extending from something like JPanel and override it's paintComponent method, performing your custom painting there (don't forget to call super.paintComponent). Take a look at Performing Custom Painting for more details
You should also avoid using KeyListener and instead use the Key Bindings API as it doesn't suffer from the same focus issues that KeyListener does...
Updated with runnable example
So I had a play around with code and produced this simple example...
Basically, I tossed out Polygon in favour of Path2D, basically because it provides much greater functionality and is easy to deal with when scaling ;)
import java.applet.Applet;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
public class MouseOver extends Applet implements KeyListener, MouseListener,
MouseMotionListener {
private double xpos, ypos;
private Path2D poly;
private double polyrot = 0;
private int width; // !! added
private int height; // !! added
public void init() {
poly = new Path2D.Double();
poly.moveTo(0, 10);
poly.lineTo(5, 0);
poly.lineTo(10, 10);
poly.lineTo(0, 10);
poly.closePath();
addKeyListener(this);
addMouseListener(this);
addMouseMotionListener(this);
}
public void paint(Graphics g) {
super.paint(g);;
Graphics2D g2d = (Graphics2D) g;
AffineTransform id = new AffineTransform();
width = getSize().width;
height = getSize().height;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, width, height);
g2d.setColor(Color.RED);
id.scale(5, 5);
Shape scaled = poly.createTransformedShape(id);
Rectangle bounds = scaled.getBounds();
g2d.translate((width - bounds.width) / 2, (height - bounds.height) / 2);
g2d.rotate(Math.toRadians(polyrot), bounds.width / 2, bounds.height / 2);
g2d.setStroke(new BasicStroke(5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2d.draw(scaled);
}
public void keyReleased(KeyEvent k) {
}
public void keyTyped(KeyEvent k) {
}
public void keyPressed(KeyEvent k) {
switch (k.getKeyCode()) {
case KeyEvent.VK_LEFT:
polyrot++;
repaint();
break;
case KeyEvent.VK_RIGHT:
polyrot--;
repaint();
break;
}
}
public void mouseEntered(MouseEvent m) {
}
public void mouseExited(MouseEvent m) {
}
public void mouseReleased(MouseEvent m) {
}
public void mouseClicked(MouseEvent m) {
}
public void mousePressed(MouseEvent m) {
switch (m.getButton()) {
case MouseEvent.BUTTON1:
polyrot--;
repaint();
break;
case MouseEvent.BUTTON2:
polyrot++;
repaint();
break;
}
}
public void mouseMoved(MouseEvent e) {
int x = width / 2;
int y = height / 2;
Point mousePoint = e.getPoint();
int deltaX = mousePoint.x - x;
int deltaY = mousePoint.y - y;
polyrot = -Math.atan2(deltaX, deltaY);
polyrot = Math.toDegrees(polyrot) + 180;
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
// You forgot this method
}
}
From here:
public void mouseMoved(MouseEvent e){
xpos=getX();
if(xpos<0){polyrot--;}
else if(xpos>0){polyrot++;}
repaint();
break;
}
It seems you update only the xpos. You should update also the variable ypos.
You might want to do it with something like this:
ypos=e.getY();
if (this.ypos<0){
this.polyrot--;
}else if (this.ypos>0) {
this.polyrot++;
}
this.repaint();

Java Applet Game 2D Window Scrolling

I'm trying to develop a 2D RPG Game in a Java Applet. Right now I've got a simple oval that the player can use Left, Right, Up and Down to move, and collisions against the borders of the applet stops them. The problem is, I want to create a giant world(2000px by 2000x) of area that the player can move. However, I want them only to see 600px by 400x of the screen at one time. If they keep moving right, I want the screen to follow them, same goes for up, down and left. Can anyone tell me how to do this? Here is my code so far:
import java.awt.*;
import java.awt.event.KeyEvent;
import java.applet.Applet;
import java.awt.event.KeyListener;
import javax.swing.*;
public class Main extends Applet implements Runnable, KeyListener
{
private Image dbImage;
private Graphics dbg;
Thread t1;
int x = 0;
int y = 0;
int prevX = x;
int prevY = y;
int radius = 40;
boolean keyReleased = false;
public void init()
{
setSize(600, 400);
}
public void start()
{
addKeyListener(this);
t1 = new Thread(this);
t1.start();
}
public void destroy()
{
}
public void stop()
{
}
public void paint(Graphics g)
{
//player
g.setColor(Color.RED);
g.fillOval(x, y, radius, radius);
}
public void update(Graphics g)
{
dbImage = createImage (this.getSize().width, this.getSize().height);
dbg = dbImage.getGraphics();
// initialize buffer
if (dbImage == null)
{
}
// clear screen in background
dbg.setColor(getBackground());
dbg.fillRect(0, 0, this.getSize().width, this.getSize().height);
// draw elements in background
dbg.setColor(getForeground());
paint(dbg);
// draw image on the screen
g.drawImage(dbImage, 0, 0, this);
}
#Override
public void run()
{
while (true)
{
//x++;
repaint();
try
{
t1.sleep(17);
}
catch (Exception e)
{
}
}
}
public boolean CheckCollision(String dir)
{
if (x <= 0 && dir.equals("L"))
{
x = prevX;
return true;
}
else if (y <= 0 && dir.equals("U"))
{
y = prevY;
return true;
}
else if (x >= (getWidth() - radius) && dir.equals("R"))
{
System.out.println(getWidth());
x = prevX;
return true;
}
else if (y >= (getHeight() - radius) && dir.equals("D"))
{
y = prevY;
return true;
}
return false;
}
#Override
public void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_RIGHT:
if (!CheckCollision("R"))
{
x += 4;
prevX = x;
}
break;
case KeyEvent.VK_LEFT:
if (!CheckCollision("L"))
{
x -= 4;
prevX = x;
}
break;
case KeyEvent.VK_UP:
if (!CheckCollision("U"))
{
y -= 4;
prevY = y;
}
break;
case KeyEvent.VK_DOWN:
if (!CheckCollision("D"))
{
y += 4;
prevY = y;
}
break;
}
}
#Override
public void keyReleased(KeyEvent arg0)
{
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0)
{
// TODO Auto-generated method stub
}
}
This is a basic example of scrolling viewable area, where the virtual world is large then the view area.
This basically maintains a number of parameters. It maintains the point where in the world the top/left of the view is and the players position within the world.
These values are converted back to real world coordinates (where 0x0 is the top left corner of the viewable area).
The examples also use BufferedImage#getSubImage to make it easier to render. You could calculate the offset position of the map to the view as well, but that comes down to needs...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MiddleEarth {
public static void main(String[] args) {
new MiddleEarth();
}
public MiddleEarth() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new WorldPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class WorldPane extends JPanel {
private BufferedImage map;
private BufferedImage party;
private Point viewPort;
private Point partyPoint;
private BufferedImage view;
public WorldPane() {
try {
map = ImageIO.read(getClass().getResource("/MiddleEarth.jpg"));
party = ImageIO.read(getClass().getResource("/8BitFrodo.png"));
viewPort = new Point(0, (map.getHeight() / 2) - 100);
partyPoint = new Point(party.getWidth() / 2, (map.getHeight() / 2)); // Virtual Point...
} catch (IOException exp) {
exp.printStackTrace();
}
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "goRight");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "goLeft");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "goUp");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "goDown");
am.put("goRight", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
moveParty(10, 0);
}
});
am.put("goLeft", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
moveParty(-10, 0);
}
});
am.put("goUp", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
moveParty(0, -10);
}
});
am.put("goDown", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
moveParty(0, 10);
}
});
}
protected void moveParty(int xDelta, int yDelta) {
partyPoint.x += xDelta;
partyPoint.y += yDelta;
Point view = fromWorld(partyPoint);
if (view.x > getWidth() - (party.getWidth() / 2)) {
viewPort.x += xDelta;
if (viewPort.x + getWidth() > map.getWidth()) {
viewPort.x = map.getWidth() - getWidth();
partyPoint.x = map.getWidth() - (party.getWidth() / 2) - 1;
}
invalidate();
} else if (view.x < party.getWidth() / 2) {
viewPort.x += xDelta;
if (viewPort.x < 0) {
viewPort.x = 0;
partyPoint.x = (party.getWidth() / 2);
}
invalidate();
}
System.out.println(view + "; " + getHeight());
if (view.y > getHeight() - (party.getHeight() / 2)) {
viewPort.y += yDelta;
if (viewPort.y + getHeight() > map.getHeight()) {
viewPort.y = map.getHeight() - getHeight();
partyPoint.y = map.getHeight() - (party.getHeight() / 2) - 1;
}
invalidate();
} else if (view.y < party.getHeight() / 2) {
viewPort.y += yDelta;
if (viewPort.y < 0) {
viewPort.y = 0;
partyPoint.y = (party.getHeight() / 2);
}
invalidate();
}
repaint();
}
#Override
public void invalidate() {
view = null;
super.invalidate();
}
public BufferedImage getView() {
if (view == null && getWidth() > 0 && getHeight() > 0) {
view = map.getSubimage(viewPort.x, viewPort.y, getWidth(), getHeight());
}
return view;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (map != null) {
g2d.drawImage(getView(), 0, 0, this);
Point real = fromWorld(partyPoint);
int x = real.x - (party.getWidth() / 2);
int y = real.y - (party.getHeight()/ 2);
g2d.drawImage(party, x, y, this);
}
g2d.dispose();
}
protected Point fromWorld(Point wp) {
Point p = new Point();
p.x = wp.x - viewPort.x;
p.y = wp.y - viewPort.y;
return p;
}
}
}
This is how I do in my engine.
I'll keep two variables OffSetX and OffSetY
And calculate them every step to center the player like this.
OffSetX = 0;
OffSetY = 0;
if (MAP_WIDTH > WINDOW_WIDTH) {
OffSetX = Math.round(WINDOW_WIDTH / 2 - obj.getX() - TILE_SIZE);
OffSetX = Math.min(OffSetX, 0);
OffSetX = Math.max(OffSetX, WINDOW_WIDTH - MAP_WIDTH);
}
if (MAP_HEIGHT > WINDOW_HEIGHT) {
OffSetY = Math.round(WINDOW_HEIGHT / 2 - obj.getY() - TILE_SIZE);
OffSetY = Math.min(OffSetY, 0);
OffSetY = Math.max(OffSetY, WINDOW_HEIGHT - MAP_HEIGHT);
}
And then draw the map at the position (OffSetX, OffSetY) i.e., just add these to the original position of the object to draw.
You may want to skip rendering objects which are not visible.

Categories