My picture is moving too slowly - java

I am currently making a kind of adventure 2D game project for university.
I have drawn an array of pictures(walls,floor etc) and then the movable hero figure. The problem: without the array the figure is moving fine but with the array the movement starts to lag hard. Is it my Pc? or is my drawing method too "heavy"? Please take a look:
import java.awt.Graphics;
import java.awt.Rectangle;
public class World {
public static int WorldW = 16 , WorldH = 16;
public SpielElement[][] element = new SpielElement[WorldW][WorldH];
public int[][] level0 ={{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0},
{0,0,0,1,1,1,1,1,1,1,1,6,0,0,0,0},
{0,0,0,1,1,1,5,1,1,1,1,1,0,0,0,0},
{0,0,0,1,1,6,1,1,2,1,5,1,0,0,0,0},
{0,0,0,1,1,1,1,5,1,1,1,1,0,0,0,0},
{0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0},
{0,0,0,0,0,1,1,3,1,1,0,0,0,0,0,0},
{0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
public int[][] level1 ={{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,1,1,1,1,2,0,1,0},
{0,4,0,1,0,0,5,1,1,1,1,1,1,0,1,0},
{0,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0},
{0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,0},
{0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0},
{0,1,1,1,0,0,1,1,1,1,1,0,0,1,0,0},
{0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0},
{0,1,0,1,1,1,1,1,1,1,1,1,0,0,3,0},
{0,1,0,1,0,0,0,0,0,1,0,1,0,0,1,0},
{0,1,0,1,1,1,1,0,0,1,0,1,0,0,1,0},
{0,1,0,1,0,0,1,0,0,1,0,1,1,1,1,0},
{0,1,0,0,0,0,1,0,0,1,0,0,1,0,0,0},
{0,1,1,1,1,6,1,1,0,1,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
public World(){
create();
}
public void create(){
for(int x = 0; x<WorldW; x++){
for(int y = 0; y<WorldH; y++){
element[x][y] = new SpielElement(x,y,level0[y][x]);
}
}
}
public void generate(Graphics g){
for(int x = 0; x<WorldW; x++){
for(int y = 0; y<WorldH; y++){
element[x][y].zeichne(g);
}
}
}
}
Well the int array is to define which kind of picture I need to draw and
i intend to first create all the Panels (SpielElement) and then draw them
Here is how i Draw them:
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class SpielElement extends JPanel{
int posX,posY,type ;
BufferedImage wand, boden, tuer, schluessel;
public SpielElement(int x, int y,int z){
this.posX = x*40;
this.posY = y*40;
this.type = z;
try {
wand = ImageIO.read(SpielElement.class.getResource("/img/wand.png"));
boden = ImageIO.read(SpielElement.class.getResource("/img/boden.png"));
tuer = ImageIO.read(SpielElement.class.getResource("/img/tuer.png"));
schluessel = ImageIO.read(SpielElement.class.getResource("/img/schluessel.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void zeichne(Graphics g){
switch(type){
case 0: g.drawImage(wand,posX,posY,boden.getWidth(),wand.getHeight(),null);
break;
case 1:g.drawImage(boden,posX,posY,boden.getWidth(),boden.getHeight(),null);
break;
case 2: g.drawImage(schluessel,posX,posY,schluessel.getWidth(),schluessel.getHeight(),null);
break;
case 3: g.drawImage(tuer,posX,posY,tuer.getWidth(),tuer.getHeight(),null);
break;
case 4: g.drawImage(boden,posX,posY,boden.getWidth(),boden.getHeight(),null);
break;
case 5:g.drawImage(boden,posX,posY,boden.getWidth(),boden.getHeight(),null);
break;
case 6: g.drawImage(boden,posX,posY,boden.getWidth(),boden.getHeight(),null);
break;
}
}
}
I hope u get what I am thinking by reading the code and hopefully see what is wrong. There are no Syntax errors whatsoever but its so damn slow. In the end added all of this onto a JPanel Board which is added on a JFrame
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Board extends JPanel implements KeyListener{
private final int BREITE = 700;
private final int HOEHE = 700;
Hunter Held ;
World Welt;
public Board(){
super();
Held = new Hunter(200,200);
Welt = new World();
this.setBackground(Color.BLACK);
}
public void paint(Graphics g){
super.paint(g);
Welt.generate(g);
Held.draw(g);
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_LEFT)
Held.posX = Held.posX - 10;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
Held.posX = Held.posX + 10;
if (e.getKeyCode() == KeyEvent.VK_UP)
Held.posY = Held.posY - 10;
if (e.getKeyCode() == KeyEvent.VK_DOWN)
Held.posY = Held.posY + 10;
this.repaint();
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
the Hero(Held) is drawn the exact way like the other images with its Coordinates beeing altered everytime i press keys and thus repainted.
I will refrain from further code dumping at this point. This is how it looks like in the end:
http://puush.me/account?pool=1468274
(Sorry no reputation yet)
The figure on Scrren moves on KeyInput but with lags...
This is my first question and i hope it is detailed enough.
Sry in advance if my problem is stupid only started 2 weeks ago with programming in general.
Constructive critizism is adviced. sry for code Dumping...

Until I saw you mentioned JPanel and JFrame, I thought it was an Android related question...
Anyway maybe you should draw them in a new thread, on an invisible canvas/image/cache, whatever... then bring it to front and draw another frame in background.
Sorry, I don't know how to do it with Swing, but I think that's how all animation frameworks work. In Android people do all these dirty work in background thread...

Related

How do I properly move drawn Polygon in Swing

I am currently working on a 2D game which will be a puzzle. I got everything set up, got all my pieces added to my board (called View) and they're all aligned properly.
My next step is to select a piece by MouseEvent#mousePressed to be able to move it with the arrow keys with KeyEvent#keyPressed. The issue I'm currently running into is that my pieces will repaint themself whenever I move or resize the window. If I click on one piece and want to move it, the other pieces move too (in a way, they should not since one step equals about 100 pixel).
If anyone could tell me where my issue is and give me some advice, I would appreciate it.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Puzzle {
public static void main(String[] args) {
SwingUtilities.invokeLater(Puzzle::new);
}
public Puzzle() {
JFrame frame = new JFrame("Puzzle");
frame.setSize(400, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
View view = new View();
view.createPieces();
frame.setContentPane(view);
view.setFocusable(true);
MouseAdapterMod listener = new MouseAdapterMod(view);
view.addMouseListener(listener);
view.addKeyListener(listener);
frame.setVisible(true);
}
}
class View extends JPanel {
final List<Piece> pieces = new ArrayList<>();
public View() {
}
void createPieces() {
Piece topLeft = new Piece(100, 100, 0, Color.YELLOW);
pieces.add(topLeft);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D gc = (Graphics2D) g;
for (Piece needle : pieces) {
needle.translate(needle.getLocation().x, needle.getLocation().y);
gc.setColor(needle.color);
gc.fill(needle);
gc.draw(needle);
}
}
}
class Piece extends Polygon {
int x;
int y;
final Color color;
Point location;
Piece(int x, int y, int type, Color color) {
this.x = x;
this.y = y;
this.color = color;
this.location = new Point(x, y);
int[] arrX = new int[] { 0, 100, 100, -100, -100, 0 };;
int[] arrY = new int[] { 0, 0, -100, -100, 100, 100 };
for (int drawIndex = 0; drawIndex < arrX.length; drawIndex++) {
addPoint(arrX[drawIndex], arrY[drawIndex]);
}
}
Point getLocation() {
return location;
}
void setLocation(Point location) {
this.location = location;
}
}
class MouseAdapterMod implements MouseListener, KeyListener {
final View view;
Polygon current;
public MouseAdapterMod(View view) {
this.view = view;
}
#Override
public void mousePressed(MouseEvent e) {
for (Piece piece : view.pieces) {
if (piece.contains(e.getX(), e.getY())) {
current = piece;
System.out.println(current);
}
}
}
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
current.translate(0, -100);
view.repaint();
break;
case KeyEvent.VK_DOWN:
current.translate(0, +100);
view.repaint();
break;
case KeyEvent.VK_LEFT:
current.translate(-100, 0);
view.repaint();
break;
case KeyEvent.VK_RIGHT:
current.translate(+100, 0);
view.repaint();
break;
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
(Sorry for the indent, stackoverflow is messing it up)
EDIT: But the problem is, eventually I want to move my pieces using Piece#setLocation to always keep track of their current x/y coordinates. I figured, I need to invoke Piece#getLocation in my painting to draw them based on the location but yet I do not know how. Using Piece#setLocation literally does nothing.
If you revert back to your Piece code from this question, you can move pieces by:
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
view.translatePiece(0, -100);
break;
case KeyEvent.VK_DOWN:
view.translatePiece(0, +100);
break;
case KeyEvent.VK_LEFT:
view.translatePiece(-100, 0);
break;
case KeyEvent.VK_RIGHT:
view.translatePiece(+100, 0);
break;
}
}
And adding to your view:
void translatePiece(int dx, int dy) {
if (current != null) {
current.x += dx;
current.y += dy;
repaint();
}
}
The if (current != null) { ... } test will prevent your application from crashing if you press an arrow key before clicking on a piece, which it currently does.
You could, instead of translating the Polygon, translate the location, and use it for painting:
In keyPressed, replace current.translate to translate the location instead of the whole Polygon (you could override Piece#translate to call current.getLocation().translate for example).
In View#paintComponent, replace:
needle.translate(needle.getLocation().x, needle.getLocation().y);
with
gc.translate(needle.getLocation().x, needle.getLocation().y);
and add
gc.translate(-needle.getLocation().x, -needle.getLocation().y);
at the end of your for-loop.
This will translate the whole Graphics2D to paint a polygon, and revert it after.

Snake Game. Handle keyPressed method

I got the snake running down, now I try to get the keypressed() method to work. I don't think it's listening from the keyboard. My idea is for example if the the down key is pressed, the variable direction is set to 1 and the switch case statement would handle that. I doubt that the direction variable was't read by the switch case.
My main class:
package com.bin.snake;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game extends JPanel{
boolean playingSnake = true;
Snake snake = new Snake();
public Game() {
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
snake.keyPressed(e);
}
});
setFocusable(true);
}
public void paint(Graphics g) {// inherit paint method of JPanel class with
// parameter g type Graphics
// parameter g is the object to paint things
super.paint(g); // erase latest image
Graphics2D g2d = (Graphics2D) g; // casting g to Graphics2D type
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// rendering
// image
snake.paint(g2d);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Snake!");
frame.setVisible(true);
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Game game = new Game();
frame.add(game);
while (true) {
game.updateGame();
game.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void updateGame() {
snake.moveSnake();
}
}
My Snake Class:
package com.bin.snake;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
public class Snake {
private Game game;
int iSnakeLength = 10;
int direction = 1;
final int SIDE = 13;
int[] snakeY = new int[2000];
int[] snakeX = new int[2000];
int xs = 0;
int ys = 0;
public void moveSnake() {
switch (direction) {
case 0:// up
snakeY[0] -=1.5;
break;
case 1:// down
snakeY[0] += 1.5;
break;
case 2:// right
snakeX[0] += 1.5;
break;
case 3:// left
snakeX[0] -=1.5;
break;
}
for (int i = iSnakeLength; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
}
public void paint(Graphics2D g) {
g.fillRect(snakeX[0], snakeY[0], SIDE, SIDE);
for (int i = 0; i < iSnakeLength; i++) {
g.fillRect(snakeX[i + 1], snakeY[i + 1], SIDE, SIDE);
}
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_DOWN){
direction = 1;
}
if(e.getKeyCode() == KeyEvent.VK_UP){
direction = 0;
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
direction = 3;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
direction = 2;
}
}
}
I don't think it's listening from the keyboard. My idea
KeyEvents are only dispatched to the component with focus. A JPanel is not focusable by default.
To make a panel focusable you use:
panel.setFocusable( true );
Other comments:
Custom painting is done by overriding the paintComponent(...) method, not the paint() method. Read the Swing tutorial on Custom Painting for more information and examples.
You should NOT be using a KeyListener. Swing was designed to be used with Key Bindings. Read the Swing tutorial on How to Use Key Bindings. You can also check out Motion Using the Keyboard which contains working examples of moving a component using Key Bindings.
For animation you should be using a Swing Timer to schedule the animation. Check the table of contents from the tutorial links I have already provided. There is a section on How to Use Swing Timers.

MouseDragged & MouseMoved not working in Java Applet

I'm currently working on a map generation program for a game I'm creating, and so I'm trying to be able to modify the individual tiles on the map using my mouse. I've successfully implemented the ability to click on a tile and change its value (from say a 4 way tile to a 2 way tile), but I am having trouble getting mouseDragged to work. According to the Java docs I've done the correct implementation of the mouseDragged interface into my MouseEventHandler, but I when I drag my mouse and move my mouse around neither of those events trip and throw the println text that I've got them throwing right now. If anyone could shed some light as to why this isn't working for me, I'd love that. Thanks!
A side question: If anyone has any better methods of trying to generate a map like this, or any (presumably anything is better than what I did) other methods of detecting individual mousePressed on a tile, I'd love to hear it. This is only my first time working with this sort of thing so I'm quite inexperienced and would love some advice.
As for the code itself:
File 1: OneQuestMapgen.java
package OneQuestMapgen;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.*;
import tiles.Tile;
import tiles.TileSet;
public class OneQuestMapgen extends JApplet{
/**
*
*/
public static OneQuestMapgen instance;
ArrayList<ArrayList<Tile>> map = new ArrayList<ArrayList<Tile>>();
TileSet tileSet = new TileSet();
public void init(){
this.setSize(950,600);
}
public void start(){
this.addMouseListener(new MouseEventListener(this));
int tileSize = tileSet.get("grasslands")[1].getHeight();
for (int i = 0; i < getHeight(); i += tileSize) {
ArrayList<Tile> temp = new ArrayList<Tile>();
for (int j = 0; j < getWidth(); j += tileSize) {
temp.add(new Tile(j, i, tileSize, tileSet.get("grasslands")));
}
map.add(temp);
}
}
public void paint(Graphics g){
for (int i = 0; i < map.size(); i++){
for(int j = 0; j < map.get(i).size(); j++){
map.get(i).get(j).render(g);
}
}
}
public void stop(){
}
public void destroy(){
}
public ArrayList<ArrayList<Tile>> getMap(){
return map;
}
}
File 2: MouseEventListener.java
package OneQuestMapgen;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import tiles.Tile;
public class MouseEventListener implements MouseListener, MouseMotionListener {
OneQuestMapgen instance;
ArrayList<ArrayList<Tile>> map;
public MouseEventListener(OneQuestMapgen instance) {
this.instance = instance;
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(e.getX() + " , " + e.getY());
map = instance.getMap();
for (int i = 0; i < map.size(); i++) {
for (int j = 0; j < map.get(i).size(); j++)
if (map.get(i).get(j).bounds(e)) {
map.get(i).get(j).onClicked(instance.getGraphics());
}
}
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseDragged(MouseEvent arg0) {
System.out.println("Mouse Dragged: " + arg0.getX() + " , " + arg0.getY());
}
#Override
public void mouseMoved(MouseEvent arg0) {
// TODO Auto-generated method stub
System.out.println("Mouse Moved: " + arg0.getX() + " , " + arg0.getY());
}
}
File 3: Tile.java
package tiles;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
#SuppressWarnings("serial")
public class Tile extends Square {
BufferedImage[] tiles;
int tileValue = 0;
public Tile (int x, int y, int size, BufferedImage[] tileSet){
super(x,y,size);
tiles = tileSet;
}
public void render(Graphics g) {
g.drawImage(tiles[tileValue], getX(), getY(), getDimension(), getDimension(), null);
}
public void onClicked(Graphics g) {
tileValue++;
System.out.println(tileValue);
g.drawImage(tiles[tileValue], getX(), getY(), getDimension(), getDimension(), null);
}
public boolean bounds(MouseEvent e){
if (e.getX() <= getX() + getDimension() && e.getX() >= getX() && e.getY() <= getY() + getDimension() && e.getY() >= getY())
return true;
return false;
}
}
File 4: TileSet.java
package tiles;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
import javax.imageio.ImageIO;
public final class TileSet {
ConcurrentHashMap<String, BufferedImage[]> container = new ConcurrentHashMap<String, BufferedImage[]>(11);
BufferedImage[] grasslands = new BufferedImage[11];
public TileSet(){
boolean toAdd = true;
try {
grasslands[0] = ImageIO.read(new URL("http://i675.photobucket.com/albums/vv118/va023/OneQuest/GrassBlank_zpse99de845.png"));
grasslands[1] = ImageIO.read(new URL("http://i675.photobucket.com/albums/vv118/va023/OneQuest/4WayTile_zps49ebbeea.png"));
grasslands[2] = ImageIO.read(new URL("http://i675.photobucket.com/albums/vv118/va023/OneQuest/LineHorizontal_zpsc7bd45d5.png"));
grasslands[3] = ImageIO.read(new URL("http://i675.photobucket.com/albums/vv118/va023/OneQuest/LineVertical_zps9719b63f.png"));
grasslands[4] = ImageIO.read(new URL("http://i675.photobucket.com/albums/vv118/va023/OneQuest/TShapeTop_zpsa4b2aaa1.png"))
}
catch (Exception e) {
System.out.println("Unable to load resources for Grasslands");
}
for (int i = 0; i < grasslands.length; i++)
if (grasslands[i].getWidth() != grasslands[i].getHeight()) {
System.out.println("Error, tiles are not square. Grasslands has not been added.");
toAdd = false;
}
if (toAdd) {
container.put("grasslands".toLowerCase(), grasslands);
}
}
public BufferedImage[] get(String s) {
return container.get(s.toLowerCase());
}
}
File 5: Square.java
package tiles;
import javax.swing.JLabel;
public abstract class Square extends JLabel{
/**
*
*/
private static final long serialVersionUID = 1L;
private int x;
private int y;
private int dimension;
public Square(int x, int y, int dimension){
this.x = x;
this.y = y;
this.dimension = dimension;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public int getDimension(){
return dimension;
}
}
Note: If you would rather be able to pull it all off of github, I've added a link to my github repo for this project below:
URL: https://github.com/vagrawal1/OneQuestMapgen
HTTPS: https://github.com/vagrawal1/OneQuestMapgen.git
SSH: git#github.com:vagrawal1/OneQuestMapgen.git
Git Read-Only: git://github.com/vagrawal1/OneQuestMapgen.git
Thanks once again for your help and thank you for taking the time to read this.
You need to add a MouseMotionListener for dragging to work. You're just adding a MouseListener.
i.e.,
public void start() {
MouseEventListener myMouseEventListener = new MouseEventListener(this);
addMouseListener(myMouseEventListener);
addMouseMotionListener(myMouseEventListener);
//this.addMouseListener(new MouseEventListener(this));
Also as per my comments, your getX() and getY() methods of the Square class override the same methods of JLabel, and that if you aren't careful with these and use them correctly they can totally mess up the placement of your components in the GUI. Myself, I take great pains to avoid overriding these very methods. Consider changing their names if overriding wasn't your intention.
Also, I tend to favor mousePressed(...) over the mouseClicked(...) method as the former will respond to the press even if you move the mouse after pressing it.
Edit: another bug! You should almost never get your Graphics instance by calling getGraphics() on a component as the Graphics object returned is evanescent and may soon become null. Instead either draw on a BufferedImage which is displayed in a JComponent or JPanel's paintComponent(...) or just draw in paintComponent(...) itself.
Edit 2: why override paint(...)? That seems a bit dangerous to me, especially since you're not calling the super method, and especially since there is no need to do this sort of thing.

How to move image in Applet?

I want to move the character left, right up, and down in applet, but it is not moving at all. here is my code, help please
import javax.swing.JPanel;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import java.applet.*;
import java.awt.event.*;
import java.awt.*;
public class drawCenter extends Applet
{
private int x,y;// the x and y of the position of the player
private BufferedImage image, pos;
public void init( )
{
try
{
image = ImageIO.read(new File("pokemonCenter.png"));
pos = ImageIO.read(new File("player/maleInGame.png"));
}
catch (IOException ex)
{
}
x = 150; y = 171;
}
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
switch( keyCode )
{
case KeyEvent.VK_UP: if( y>0 )
{
y=y-19;
repaint();
}
break;
case KeyEvent.VK_DOWN: if( y<171 )
{
y=y+19;
repaint();
}
break;
case KeyEvent.VK_LEFT:if( x>0 )
{
x=x-15;
repaint();
}
break;
case KeyEvent.VK_RIGHT:if( x<285 )
{
x=x+15;
repaint();
}
break;
}
e.consume();
}
public void keyReleased(){
}
public void paint( Graphics g )
{
g.drawImage(image, 0, 0, null);
g.drawImage(pos, x, y, null);
}
}
Your code is pretending to have a KeyListener, but there is no KeyListener anywhere to be found, much less one added to a component of the GUI. Your solution: create a class that implements KeyListener or that extends KeyAdapter, and then add it to a GUI component that has focus.
Please check out: How to Write a KeyListener.
Also, I recommend that you avoid having your GUI class, your Applet, implement KeyListener since that can give the class too much to be responsible for. Better I think to either create an anonymous inner class or even a separate stand-alone class for your KeyListener.
Make your class implement KeyListener and then call super.addKeyListener(this) in your constructor. As you have it now, you're neither specifying the class implements the interface (despite implementing the methods it would need to) nor are you ever registering a listener with the Applet.
Try this.
import javax.swing.*;
import java.awt.*;
import static java.awt.event.KeyEvent.*;
public class DrawCenter extends JApplet implements KeyListener {
Image character = null;
int x = 0;
int y = 0;
public Image loadImage(String name){
return new ImageIcon(getClass().getClassLoader().getResource(name)).getImage();
}
public void init(){
character = getImage("pokemonCenter.png");
x = getWidth()/2 - character.getWidth(null)/2;
y = getHeight()/2 - character.getHeight(null)/2;
addKeyListener(this);
}
public void keyPressed(KeyEvent e){
switch (e.getKeyCode()){
case VK_LEFT: x--; break;
case VK_RIGHT: x++; break;
case VK_UP: y--; break;
case VK_DOWN: y++; break;
}
repaint();
}
public void paint(Graphics g){
g.drawImage(character, x, y, null);
}
}
If you're making a game see the game loops or try a Game-Engine (If you'r interested, go to
http://game-engine-for-java.googlecode.com/ )
You should be something like this:
package stack;
import java.applet.*;
import java.awt.event.*;
import java.awt.*;
public class DrawCenter extends Applet implements KeyListener{
private int x=50,y=50;// the x and y of the position of the player
public void init( ){
addKeyListener(this);
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch( keyCode ) {
case KeyEvent.VK_UP: if( y>0 ){ //when up key is pressed and the position of the player is not on the edge
y=y-19;
repaint();
}
break;
case KeyEvent.VK_DOWN: if( y<171 ){//when down key is pressed and the position of the player is not on the edge
y=y+19;
repaint();
}
break;
case KeyEvent.VK_LEFT: if( x>0 ){
x=x-15;
repaint();
}
break;
case KeyEvent.VK_RIGHT: if( x<285 ){
x=x+15;
repaint();
}
break;
}
}
public void keyReleased(){
}
public void paint( Graphics g ){ //will draw the background and the character
g.fillRect(x, y, 20, 20);
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}

left-click revert - rectangle, mouseClickedEvent

I've created a basic Java program that creates a rectangle on startup and every time it is clicked, the rectangle grows and changes to a different (random) color. here's my code:
package rectPAK;
import javax.swing.JFrame;
public class DisplayRect {
public static void main(String[] args) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(0,0,1000,1000);
window.getContentPane().add(new MyCanvas());
window.setVisible(true);
}
}
and then myCanvas is this:
package rectPAK;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Random;
import javax.swing.JComponent;
public class MyCanvas extends JComponent{
int W = 100;
int H = 100;
int r;
int g;
int b;
int trans;
int maxRandNum = 255;
int xPoint;
int yPoint;
public MyCanvas() {
this.addMouseListener(m);
this.addMouseMotionListener(ml);
}
Random rand = new Random();
MouseListener m = new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
W = W + 20;
H = H + 20;
r = rand.nextInt(maxRandNum);
g = rand.nextInt(maxRandNum);
b = rand.nextInt(maxRandNum);
trans = rand.nextInt(maxRandNum);
repaint();
}
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
};
MouseMotionListener ml = new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent e) {
Point p = e.getLocationOnScreen();
xPoint = p.x;
yPoint = p.y;
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
};
public void paint(Graphics gr) {
gr.setColor(Color.BLACK);
gr.drawRect(xPoint, yPoint, W, H);
gr.setColor(new Color(r,g,b,trans));
gr.fillRect(xPoint, yPoint, W, H);
}
}
now my question is this: how do i make it so that when i right-click on the rectangle, it reverts to the previous size and color? i Know it's a lot to ask, but i cant find anything about it...
Thanks a lot.
Use a set of "previous" variables (eg previousX, previousY, previousR, etc) to store the old info before every update, and create a right click event to call a method like your paint method to set the object's variables to previousX, previousY, etc.
Every time you generate a random number, store it as the previous instance. This way you will be able to go back one step. If you want to go back all the way to the first one, then you should store each created rectangle's parameters in an stack of sorts, where you could pop out each previous stage.
Once that is done you should create a method for handling right clicks, and in that method, you should set the rectangles parameters to the previous value.

Categories