i want to select rows in grid on mouse drag for that i have following piece of code :
my mouse event listener is DragMultiSelectListener.java
import java.util.List;
import com.myexample.client.ui.items.AbstractContentItem;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
public class DragMultiSelectListener implements Listener<BaseEvent> {
Presenter presenter = null;
/* multiple select on drag */
private boolean mousePressed = false;
private boolean dragEnable = false;
private boolean selected = false;
private List<AbstractContentItem> currentSelected = null;
private int startIndex = -1;
private int endIndex = -1;
private int startX=0;
private int startY=0;
private int endX=0;
private int endY=0;
/** mouseMovedStarted used for preventing calling Grid onClick event for IE while using multiple select on DND **/
private boolean mouseMovedStarted = false;
public DragMultiSelectListener(Presenter pPresenter) {
this.presenter = pPresenter;
}
#Override
public void handleEvent(BaseEvent be) {
if(be.getType() == Events.OnMouseDown){
GridEvent ge = (GridEvent) be;
/* Multiple Row Select */
mouseMovedStarted = false;
mousePressed = true;
startIndex = ge.getRowIndex();
/* Deselect All */
if(ge.getTarget().getClassName().equals("x-grid3-scroller")){
if(ge.getTarget().getClientWidth() < ge.getTarget().getScrollWidth()){
if(ge.getTarget().getClientHeight() < (ge.getClientY() - ge.getTarget().getAbsoluteTop())){
mousePressed = false;
}
if(ge.getTarget().getClientWidth() < (ge.getClientX() - ge.getTarget().getAbsoluteLeft())){
mousePressed = false;
}
}
presenter.deselectAllContentItem();
}
/* Select Record */
if(currentSelected != null && (!presenter.getSelectedContent().isEmpty())){
selected = false;
for(AbstractContentItem item : currentSelected){
AbstractContentItem clickedItem = (AbstractContentItem) ge.getGrid().getStore().getAt(ge.getRowIndex());
if(clickedItem != null && item.getDTO().getId() == clickedItem.getDTO().getId()){
selected = true;
}
}
}else{
currentSelected = presenter.getSelectedContent();
selected = false;
}
dragEnable = false;
if(ge.getTarget().getNodeName().equalsIgnoreCase("SPAM")){
dragEnable = true;
}
if(selected){
dragEnable = true;
}
/* draw box */
if(mousePressed){
startX = ge.getClientX();
startY = ge.getClientY();
}
}else if(be.getType() == Events.OnMouseMove){
GridEvent ge = (GridEvent) be;
if(mousePressed && !dragEnable && (ge.getRowIndex() != -1) ){
if(startIndex == -1){
startIndex = ge.getRowIndex();
}
endIndex = ge.getRowIndex();
presenter.deselectAllContentItem();
if((startIndex - endIndex) >= 0){
for(int i = endIndex; i<=startIndex; i++ ){
presenter.selectContentItem(i, true);
}
}else{
for(int i = startIndex; i<=endIndex; i++ ){
presenter.selectContentItem(i, true);
}
}
/* Show selection box */
endX = ge.getClientX();
endY = ge.getClientY();
}else if(mousePressed && !dragEnable){
/* Show selection box */
endX = ge.getClientX();
endY = ge.getClientY();
if(ge.getTarget().getClassName().equals("x-grid3-scroller")){
if(startY > endY){
presenter.deselectAllContentItem();
}
}
displaySelectionBox(ge.getGrid().getAbsoluteLeft(), ge.getGrid().getAbsoluteTop());
}
mouseMovedStarted = true;
}else if(be.getType() == Events.OnMouseUp){
GridEvent ge = (GridEvent) be;
mousePressed = false;
currentSelected = presenter.getSelectedContent();
}
}
public boolean isMouseMovedStarted() {
return mouseMovedStarted;
}
public boolean isDragEnable() {
return dragEnable;
}
public void setEndX(int endX) {
this.endX = endX;
}
public void setEndY(int endY) {
this.endY = endY;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public List<AbstractContentItem> getCurrentSelected() {
return currentSelected;
}
public void setCurrentSelected(List<AbstractContentItem> currentSelected) {
this.currentSelected = currentSelected;
}
public void setMousePressed(boolean mousePressed) {
this.mousePressed = mousePressed;
}
}
Register grid event by following code
dragMultiSelectListener = new DragMultiSelectListener(presenter);
grid.addListener(Events.OnMouseDown, dragMultiSelectListener);
grid.addListener(Events.OnMouseMove, dragMultiSelectListener);
grid.addListener(Events.OnMouseUp, dragMultiSelectListener);
problem is that when i move mouse fast than it will skip selecting some of row.
i don't understand, how to improve execution speed to prevent of skipping rows.
Thanks
You can select all rows from dragStart x y, till your current x y. Only thing, you will need row hight to calculate rows then.
Related
I have the following code:
package myprojectgame.entities.creature;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import myprojectgame.Game;
import myprojectgame.Handler;
import myprojectgame.gfx.Animation;
import myprojectgame.gfx.Assets;
import myprojectgame.input.KeyManager;
import static myprojectgame.input.KeyManager.keys;
public abstract class Player extends Creature {
// Animations ---> while moving
private Animation down;
private Animation up;
private Animation left;
private Animation right;
// Animations --> idle
private Animation down_idle;
private Animation up_idle;
private Animation left_idle;
private Animation right_idle;
// Last pressed boolean variable --> initialize it to down
public boolean lastPressed = handler.getKeyManager().down;
public Player(Handler handler,float x, float y) {
super(handler,x, y,Creature.DEFAULT_CREATURE_WIDTH,Creature.DEFAULT_CREATURE_HEIGHT);
bounds.x = 16;
bounds.y = 14;
bounds.width = 25;
bounds.height = 43;
// Animations --> while moving instantiation
down = new Animation(300,Assets.player_down);
left = new Animation(300,Assets.player_left);
right = new Animation(300,Assets.player_right);
up = new Animation(300,Assets.player_up);
// Animations --> while idle instantiation
down_idle= new Animation(500,Assets.player_down_idle);
right_idle= new Animation(500,Assets.player_right_idle);
left_idle= new Animation(500,Assets.player_left_idle);
up_idle= new Animation(500,Assets.player_up_idle);
}
#Override
public void tick() {
down.tick();
up.tick();
right.tick();
left.tick();
down_idle.tick();
up_idle.tick();
right_idle.tick();
left_idle.tick();
getInput();
move();
handler.getCamera().centerOnEntity(this);
}
private void getInput() {
xMove = 0;
yMove = 0;
if (handler.getKeyManager().up) {
yMove = -speed;
lastPressed = handler.getKeyManager().up;
}
if (handler.getKeyManager().down) {
yMove = speed;
lastPressed = handler.getKeyManager().down;
}
if (handler.getKeyManager().left) {
xMove = -speed;
lastPressed = handler.getKeyManager().left;
}
if (handler.getKeyManager().right) {
xMove = speed;
lastPressed = handler.getKeyManager().right;
}
}
#Override
public void render(Graphics g) {
g.drawImage(getCurrentAnimationFrame(),(int) (x - handler.getCamera().getxOffset()), (int) (y - handler.getCamera().getyOffset()),(width),(height), null);
}
private BufferedImage getCurrentAnimationFrame() {
if (handler.getKeyManager().left && lastPressed == handler.getKeyManager().left) {
return left.getCurrentFrame();
} else if ( !(handler.getKeyManager().left)) {
return left_idle.getCurrentFrame();
}
if (handler.getKeyManager().right && lastPressed == handler.getKeyManager().right) {
return right.getCurrentFrame();
} else if ( !(handler.getKeyManager().right) && lastPressed == handler.getKeyManager().right) {
return right_idle.getCurrentFrame();
}
if (handler.getKeyManager().up && lastPressed == handler.getKeyManager().up) {
return up.getCurrentFrame();
} else if ( !(handler.getKeyManager().up) && lastPressed == handler.getKeyManager().up ) {
return up_idle.getCurrentFrame();
}
if (handler.getKeyManager().down && lastPressed == handler.getKeyManager().down) {
return down.getCurrentFrame();
} else if ( !(handler.getKeyManager().down) && lastPressed ==
handler.getKeyManager().down ) {
return down_idle.getCurrentFrame();
}
return null;
}
}
The problem is that I cannot get my getCurrentAnimationFrame() method to return the proper idle animations(or in this iteration of my code,any other animation besides left and left_idle).
My keys are defined in my KeyManager class like this:
up = keys[KeyEvent.VK_W] || keys[KeyEvent.VK_UP];
down = keys[KeyEvent.VK_S] || keys[KeyEvent.VK_DOWN];
left = keys[KeyEvent.VK_A] || keys[KeyEvent.VK_LEFT];
right = keys[KeyEvent.VK_D] || keys[KeyEvent.VK_RIGHT];
How can I properly implement Key events/strokes to return the right animations on key release/key press?
Your conditions and boolean logic are overcomplicated:
private void getInput() {
xMove = 0;
yMove = 0;
if (handler.getKeyManager().up) {
yMove = -speed;
lastPressed = handler.getKeyManager().up;
}
//...
}
private BufferedImage getCurrentAnimationFrame() {
if (handler.getKeyManager().left && lastPressed == handler.getKeyManager().left) {
return left.getCurrentFrame();
} else if ( !(handler.getKeyManager().left)) {
return left_idle.getCurrentFrame();
}
//...
return null;
}
Is same as:
private void getInput() {
xMove = 0;
yMove = 0;
KeyManager km = handler.getKeyManager();
if (km.up) {
yMove = -speed;
lastPressed = true;
}
//...
}
private BufferedImage getCurrentAnimationFrame() {
KeyManager km = handler.getKeyManager();
if (km.left && lastPressed) {
// replaced lastPressed == handler.getKeyManager().left since km.left must be true
return left.getCurrentFrame();
} else if (!km.left) {
return left_idle.getCurrentFrame();
}
//...
return null;
}
I do not see where are you setting lastPressed to false, looks to me it will be set to true (with first key press) and remains true. Since it is always true, your condition in getCurrentAnimationFrame is effectively:
private BufferedImage getCurrentAnimationFrame() {
KeyManager km = handler.getKeyManager();
if (km.left) {
return left.getCurrentFrame();
} else {
return left_idle.getCurrentFrame();
}
//UNREACHABLE CODE!
return null;
}
Even if it doesn't remain true, your code is like if left, return left animation, if not left return left idle animation. I think your somehow mixed booleans with key codes as you say "lastPressed variable is supposed to store the value of the last pressed key".
I would probably define direction enum:
public enum DirectionEnum {
LEFT, RIGHT, UP, DOWN;
}
And use it like this:
DirectionEnum lastPressed = null;
private void getInput() {
xMove = 0;
yMove = 0;
KeyManager km = handler.getKeyManager();
if (km.up) {
yMove = -speed;
lastPressed = DirectionEnum.UP;
}
//...
}
private BufferedImage getCurrentAnimationFrame() {
KeyManager km = handler.getKeyManager();
if (lastPressed == null) {
if (km.left) {
return left.getCurrentFrame();
}
//...
} else {
switch (lastPressed) {
case DOWN:
if (!km.down){
return down_idle.getCurrentFrame();
}
break;
//...
default:
throw new RuntimeException("Invalid direction " + lastPressed);
}
}
return null;
}
But I do not know if it is correct, because lastPressed will be null only first time (or never), and then you will see only idle animations. So you should probably decide when to set lastPressed back to null?
I'm trying to do the classic Snake game in Swing and I managed to make Snake move, but when it moves, it becomes infinitely long because it never erases its tail.
I have been using validate() and repaint() but nothing works.
Problem
This is my code:
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class controls extends JPanel implements KeyListener, ActionListener { // Amb aquestes dues implementacions, fem que el programa pugui rebre per teclat
// Mida serp
private int[] longXserp = new int[750];
private int[] longYserp = new int[750];
// Longitut inicial de la serp
private int serplong = 3;
// Moviments que fem
private int moviments = 0;
// Controls
private boolean esquerra = false;
private boolean dreta = false;
private boolean amunt = false;
private boolean avall = false;
// Gràfics de moviment
private ImageIcon serpesquerra;
private ImageIcon serpdreta;
private ImageIcon serpamunt;
private ImageIcon serpavall;
private Timer timer;
private int velocitatserp = 100;
private ImageIcon serp;
public controls() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
timer = new Timer(velocitatserp, this);
timer.start();
}
public void paint(Graphics g) { // Mètode amb el que imprimim per pantalla. Ha d'anomenar-se "paint", o si no, no funcionarà
if(moviments == 0) {
longXserp[2] = 50;
longXserp[1] = 75;
longXserp[0] = 100;
longYserp[2] = 100;
longYserp[1] = 100;
longYserp[0] = 100;
}
serpdreta = new ImageIcon("src/grafics/serpdreta.png");
serpdreta.paintIcon(this, g, longXserp[0], longYserp[0]);
for(int a = 0; a < serplong; a++) {
if(a == 0 && esquerra) {
serpesquerra = new ImageIcon("src/grafics/serpesquerra.png");
serpesquerra.paintIcon(this, g, longXserp[a], longYserp[a]);
}
if(a == 0 && dreta) {
serpdreta = new ImageIcon("src/grafics/serpdreta.png");
serpdreta.paintIcon(this, g, longXserp[a], longYserp[a]);
}
if(a == 0 && amunt) {
serpamunt = new ImageIcon("src/grafics/serpamunt.png");
serpamunt.paintIcon(this, g, longXserp[a], longYserp[a]);
}
if(a == 0 && avall) {
serpavall = new ImageIcon("src/grafics/serpavall.png");
serpavall.paintIcon(this, g, longXserp[a], longYserp[a]);
}
if(a != 0) {
serp = new ImageIcon("src/grafics/serp.png");
serp.paintIcon(this, g, longXserp[a], longYserp[a]);
}
}
g.dispose();
}
#Override
public void keyPressed(KeyEvent ke) {
if(ke.getKeyCode() == KeyEvent.VK_RIGHT){ // Si polses la tecla X, la seva variable boolean es posa en true
moviments++;
dreta = true;
if(!esquerra) {
dreta = true;
}
else {
dreta = false;
esquerra = true;
}
amunt = false;
avall = false;
}
if(ke.getKeyCode() == KeyEvent.VK_LEFT){
moviments++;
esquerra = true;
if(!dreta) {
esquerra = true;
}
else {
esquerra = false;
dreta = true;
}
amunt = false;
avall = false;
}
if(ke.getKeyCode() == KeyEvent.VK_UP){
moviments++;
amunt = true;
if(!avall) {
amunt = true;
}
else {
amunt = false;
avall = true;
}
esquerra = false;
dreta = false;
}
if(ke.getKeyCode() == KeyEvent.VK_DOWN){
moviments++;
avall = true;
if(!amunt) {
avall = true;
}
else {
amunt = true;
avall = false;
}
esquerra = false;
dreta = false;
}
}
#Override
public void keyReleased(KeyEvent ke) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent ke) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent ae) {
timer.start();
if(dreta) {
for(int d = serplong-1; d>=0; d--) {
longYserp[d+1] = longYserp[d];
}
for(int e = serplong; e>= 0; e--) {
if(e==0) {
longXserp[e] = longXserp[e] + 25;
}
else {
longXserp[e] = longXserp[e-1];
}
if(longXserp[e] > 850) {
longXserp[e] = 25;
}
}
repaint(); // Mètode per refrescar els gràfics tornant a cridar al mètode paint(). Es usa quan es realitzan canvis sobre els gràfics
}
if(esquerra) {
for(int d = serplong-1; d>=0; d--) {
longYserp[d+1] = longYserp[d];
}
for(int d = serplong; d>= 0; d--) {
if(d==0) {
longXserp[d] = longXserp[d] - 25;
}
else {
longXserp[d] = longXserp[d-1];
}
if(longXserp[d] < 25) {
longXserp[d] = 850;
}
}
repaint();
}
if(amunt) {
for(int d = serplong-1; d>=0; d--) {
longXserp[d+1] = longXserp[d];
}
for(int d = serplong; d>= 0; d--) {
if(d==0) {
longYserp[d] = longYserp[d] - 25;
}
else {
longYserp[d] = longYserp[d-1];
}
if(longYserp[d] < 75) {
longYserp[d] = 625;
}
}
repaint();
}
if(avall) {
for(int d = serplong-1; d>=0; d--) {
longXserp[d+1] = longXserp[d];
}
for(int d = serplong; d>= 0; d--) {
if(d==0) {
longYserp[d] = longYserp[d] + 25;
}
else {
longYserp[d] = longYserp[d-1];
}
if(longYserp[d] > 625) {
longYserp[d] = 75;
}
}
repaint();
}
}
}
I've been trying to figure out what's wrong for days. What is wrong with the above code?
public void paint(Graphics g) { ..
This should be:
public void paintComponent(Graphics g) {
super.paintComponent(g); ..
Note two important differences:
Override paintComponent for any class that is or extends JComponent.
Call the super method when custom painting to erase the previous drawings.
Other tips now I look more closely at the code:
serpdreta = new ImageIcon("src/grafics/serpdreta.png"); This type of resource loading should not be done in a paint method, which are expected to be completed in a minimal time. Instead load the image(s) when the class is constructed and store them as fields of the class, to then be used whenever needed.
But that path will likely fail when the app. is turned into a Jar. The src directory is typically not included.
Application resources will become embedded resources by the time of deployment, so it is wise to start accessing them as if they were, right now. An embedded-resource must be accessed by URL rather than file. See the info. page for embedded resource for how to form the URL.
If the app. needs to paint images, create an Image rather than an ImageIcon.
For better feedback when loading images, use ImageIO.read(..) rather than creating an ImageIcon as it will fail silently while ImageIO will provide useful information as to the cause of any problems.
For Swing, we typically use key bindings rather than the lower level KeyListener.
So I've been working on this chess app for about a week now (a few hours a day)-- and I seem to have hit a snag. All of the pieces move as they should, with collision and all-- I have promotion and castling working, and I can successfully check for being in check.
However, I can't seem to check if a move legally gets out of check. My current approach is to move the piece-- check if the person is still in check, and if not then the move is legal.
It seems that when I do this, however, it doesn't correctly calculate the check after the faux-move.
Any help would be great.
public abstract class Piece {
private Type type = Type.BLANK;
private int locX, locY, preX, preY;
private Player player;
private boolean moved = false;
Piece(Type type, int locX, int locY, Player player) {
this.locX = locX;
this.locY = locY;
this.player = player;
this.type = type;
}
public void movePiece(int x, int y) {
if (player.isTurn()) {
if (isLegalMove(x, y)) {
if (checkCollision(x, y)) {
if (clearsCheck(x, y)) {
preX = locX;
preY = locY;
setLoc(x, y);
specialPreMove(x, y);
moved = true;
Chess.chessBoard.bitBoard[preX][preY] = null;
if (Chess.chessBoard.bitBoard[x][y] != null) {
Chess.chessBoard.bitBoard[x][y].getPlayer().pieces.remove(Chess.chessBoard.bitBoard[x][y]);
}
Chess.chessBoard.bitBoard[x][y] = this;
specialPostMove(x, y);
Chess.chessBoard.getGui().repaint();
Chess.changeTurns();
}
}
}
}
}
protected void specialPreMove(int x, int y) {}
protected void specialPostMove(int x, int y) {}
protected abstract boolean checkCollision(int x, int y);
protected abstract boolean isLegalMove(int x, int y);
private boolean clearsCheck(int x, int y) {
boolean checkCk = false;
preX = locX;
preY = locY;
setLoc(x, y);
Piece locPiece = null;
Chess.chessBoard.bitBoard[preX][preY] = null;
if (Chess.chessBoard.bitBoard[x][y] != null) {
locPiece = Chess.chessBoard.bitBoard[x][y];
Chess.chessBoard.bitBoard[x][y].getPlayer().pieces.remove(Chess.chessBoard.bitBoard[x][y]);
System.out.println("Piece there: " + locPiece);
}
Chess.chessBoard.bitBoard[x][y] = this;
System.out.println(Chess.chessBoard.bitBoard[x][y]);
Chess.chessBoard.getGui().repaint();
Chess.checkCheck();
checkCk = !player.inCheck();
setLoc(preX, preY);
Chess.chessBoard.bitBoard[preX][preY] = this;
if (locPiece != null) {
Chess.chessBoard.bitBoard[x][y] = locPiece;
Chess.chessBoard.bitBoard[x][y].getPlayer().pieces.add(Chess.chessBoard.bitBoard[x][y]);
} else {
Chess.chessBoard.bitBoard[x][y] = null;
}
System.out.println(checkCk);
return checkCk;
}
public ArrayList<Move> getLegalMoves() {
ArrayList<Move> moves = new ArrayList<Move>();
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
if (isLegalMove(row, col) && checkCollision(row, col)) {
moves.add(new Move(row, col));
}
}
}
return moves;
}
is the piece class, and then the check method
public static void checkCheck() {
for (Move m : player1.getLegalMoves()) {
if (m.getX() == player2.getKing().getLocX()
&& m.getY() == player2.getKing().getLocY()) {
player2.setCheck(true);
System.out.println("IN CHECK PLAYER 2");
break;
}
}
for (Move m : player2.getLegalMoves()) {
if (m.getX() == player1.getKing().getLocX()
&& m.getY() == player1.getKing().getLocY()) {
player1.setCheck(true);
System.out.println("IN CHECK PLAYER 1");
break;
}
}
}
and then here is some other stuff that is useful
public class Player {
private Color color;
private Direction direction;
private boolean turn;
private boolean check = false;
public ArrayList<Piece> pieces = new ArrayList<>();
public Player(Color color, Direction direction) {
this.color = color;
this.turn = false;
this.direction = direction;
}
public ArrayList<Move> getLegalMoves() {
ArrayList<Move> moves = new ArrayList<>();
for (Piece p : pieces) {
for (Move m : p.getLegalMoves()) {
moves.add(m);
}
}
return moves;
}
public Piece getKing() {
for (Piece p : pieces) {
if (p.getType() == Type.KING) {
return p;
}
}
return null;
}
Looks like once you set a player in check you're not setting his status later on to unchecked.
public static void checkCheck() {
boolean isInCheck = false;
for (Move m : player1.getLegalMoves()) {
if (m.getX() == player2.getKing().getLocX()
&& m.getY() == player2.getKing().getLocY()) {
isInCheck = true;
System.out.println("IN CHECK PLAYER 2");
break;
}
}
player2.setCheck(isInCheck);
isInCheck = false;
for (Move m : player2.getLegalMoves()) {
if (m.getX() == player1.getKing().getLocX()
&& m.getY() == player1.getKing().getLocY()) {
isInCheck = true;
System.out.println("IN CHECK PLAYER 1");
break;
}
}
player1.setCheck(isInCheck);
}
I am trying to add a ball into a JPanel, however, I am unsure how to do this Below is the code I currently have for adding the ball into the JPanel. I am trying to add multiple balls in a random location onto the screen. The first appears as expected but any more than that don't appear on the screen.
Ball class;
public class Ball extends Component {
public static double ballX = rand.nextInt(500) + 40;
public static double ballY = rand.nextInt(300) + 10;
public static Ball[] balls = new Ball[20];
public Ball() {
}
public void draw(Graphics g2) {
Color color = new Color(r, g, b);
g2.setColor(color);
g2.fillOval((int) ballX, (int) ballY, 30, 30);
}
}
Method trying to add a ball into the JPanel;
public class BallFrames extends JFrame {
/* creates static varibles privite for use withing class and public for
use out side of the class */
public static final JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
public static final JPanel ballPanel = new JPanel();
public static JButton button;
public static JPanel displayPanel = new JPanel(new BorderLayout());
private static int FRAME_WIDTH = 600;
private static int FRAME_HEIGHT = 600;
/**
* constructor called method to create the components
*/
public BallFrames() {
setSize(FRAME_WIDTH,FRAME_HEIGHT);
createComponents(); // creates all compononents
}
/*
* calls helper methods to create all of the componanats needed
*/
private void createComponents() {
ActionListener listener = new BallListener();
createPanel(); // creates a panel
createButtons(listener); // Creates a button
createSlider();
}
/**
* method to create panels
*/
public void createPanel() {
BallComponent component = new BallComponent(); // creates a new BallCompoenet
displayPanel.add(component, BorderLayout.CENTER);
displayPanel.add(controlPanel, BorderLayout.SOUTH); // adds thecontrol panel
add(displayPanel); // adds the dice to the JFrame
}
public static void addBall() throws InterruptedException {
Ball.balls[BallListener.balls] = new Ball();
System.out.println(BallListener.balls); // testing
ballPanel.add(Ball.balls[BallListener.balls]);
// ballPanel.add(ball);
Runnable r = new BallRunnable();
Thread t = new Thread(r);
t.start();
t.join();
ballPanel.repaint();
}
How I am drawing them;
public class BallComponent extends JComponent {
/**
* calls paintComponenet to render images on the screen
*
* #param g
*/
#Override
public void paintComponent(Graphics g) {
int delay = 1000;
super.paintComponent(g); // call to super
Graphics2D g2 = (Graphics2D) g; // recover the graphic
TimerListener listener = new TimerListener();
Timer t = new Timer(delay, listener);
if (BallListener.gameOn == true) {
for(int i = 0; i < BallListener.balls; i++){
Ball.balls[i].draw(g2);
}
BallFrames.displayPanel.repaint();
}
}
ActionListener for the buttons;
public class BallListener implements ActionListener {
public static boolean gameOn = false;
public static int balls = 0;
/**
* gets the which button has been pressed and responds appriately
*
* #param event based on the event it will preform selected actions
*/
#Override
public void actionPerformed(ActionEvent event) {
String action = event.getActionCommand();
switch (action) {
case "start":
gameOn = true;
{
try {
BallFrames.addBall();
} catch (InterruptedException ex) {
Logger.getLogger(BallListener.class.getName()).log(Level.SEVERE, null, ex);
}
balls++;
}
BallFrames.displayPanel.repaint();
break;
case "pause":
break;
}
}
Ball Runnable;
public class BallRunnable implements Runnable {
private static Random rand = new Random();
public static boolean goLeft = true;
public static boolean goRight = false;
public static boolean goUp = false;
public static boolean goDown = false;
public static boolean diagonalUp = false;
public static boolean diagonalDown = false;
public static double speed = 0.2f;
public BallRunnable() {
}
public void run() {
boundsCheckY1();
boundsCheckX1();
boundsCheckY2();
boundsCheckX2();
}
public void boundsCheckX1() {
int temp;
if (Ball.ballX < 1) {
temp = rand.nextInt(5) + 1;
if(temp == 1) {
goRight = true;
goLeft = false;
goUp = false;
goDown = false;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 2) {
goRight = true;
goUp = true;
goDown = false;
goLeft = false;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 3) {
goRight = true;
goUp = false;
goDown = true;
goLeft = false;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 4) {
goRight = true;
goUp = false;
goDown = false;
goLeft = false;
diagonalUp = true;
diagonalDown = false;
} else if (temp == 5) {
goRight = true;
goUp = false;
goDown = false;
goLeft = false;
diagonalUp = false;
diagonalDown = true;
}
}
}
public void boundsCheckY1(){
int temp;
if (Ball.ballY < 1) {
temp = rand.nextInt(5) + 1;
if(temp == 1) {
goRight = false;
goLeft = false;
goUp = false;
goDown = true;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 2) {
goRight = false;
goUp = false;
goDown = true;
goLeft = true;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 3) {
goRight = true;
goUp = false;
goDown = true;
goLeft = false;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 4) {
goRight = true;
goUp = false;
goDown = true;
goLeft = false;
diagonalUp = false;
diagonalDown = true;
} else if (temp == 5) {
goRight = false;
goUp = false;
goDown = true;
goLeft = true;
diagonalUp = false;
diagonalDown = true;
}
}
}
public void boundsCheckX2 () {
int temp;
if (Ball.ballX > 559) {
temp = rand.nextInt(5) + 1;
if(temp == 1) {
goRight = false;
goLeft = true;
goUp = false;
goDown = false;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 2) {
goRight = false;
goUp = true;
goDown = false;
goLeft = true;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 3) {
goRight = false;
goUp = false;
goDown = true;
goLeft = true;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 4) {
goRight = false;
goUp = false;
goDown = false;
goLeft = true;
diagonalUp = true;
diagonalDown = false;
} else if (temp == 5) {
goRight = false;
goUp = false;
goDown = false;
goLeft = true;
diagonalUp = false;
diagonalDown = true;
}
}
}
public void boundsCheckY2() {
int temp;
if (Ball.ballY > 470) {
temp = rand.nextInt(5) + 1;
if(temp == 1) {
goRight = false;
goLeft = false;
goUp = true;
goDown = false;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 2) {
goRight = false;
goUp = true;
goDown = false;
goLeft = true;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 3) {
goRight = true;
goUp = true;
goDown = false;
goLeft = false;
diagonalUp = false;
diagonalDown = false;
} else if (temp == 4) {
goRight = true;
goUp = true;
goDown = false;
goLeft = false;
diagonalUp = true;
diagonalDown = false;
} else if (temp == 5) {
goRight = false;
goUp = true;
goDown = false;
goLeft = true;
diagonalUp = true;
diagonalDown = false;
}
}
}
}
The viewer class;
public class BallViewer {
/**
* creates the main frame
*
* #param args
*/
public static void main(String[] args) throws InterruptedException {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
// If Nimbus is not available, you can set the GUI to another look and feel.
}
// new BallFrames().setVisible(true);
JFrame frame = new BallFrames(); // creates new JFrame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Multi-Treaded Balls");// Sets the Title
frame.setVisible(true); // Makes the frame visible
frame.setResizable(false);
}
});
}
}
the timer listener;
public class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
String action = event.getActionCommand();
try {
movement();
} catch (InterruptedException ex) {
Logger.getLogger(TimerListener.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void movement() throws InterruptedException {
if(goLeft == true) {
Ball.ballX -= speed;
}
if(goRight == true) {
Ball.ballX += speed;
}
if(goUp == true) {
Ball.ballY -= speed;
}
if(goDown == true) {
Ball.ballY += speed;
}
if(diagonalUp == true) {
Ball.ballY += speed / 2;
}
if(diagonalDown == true) {
Ball.ballY -= speed / 2;
}
}
}
I want to be able to add more than one ball on the screen at a given time, which also moves around like the first ball.
Your definition of the ball class is behaving as expected:
public class Ball extends Component {
public static double ballX = rand.nextInt(500) + 40;
public static double ballY = rand.nextInt(300) + 10;
public static Ball[] balls = new Ball[20];
public Ball() {
}
public void draw(Graphics g2) {
Color color = new Color(r, g, b);
g2.setColor(color);
g2.fillOval((int) ballX, (int) ballY, 30, 30);
}
}
All of the static fields are shared between all instances of the class. That's what static means. All Balls have the same ballX and ballY coordinates.
What you are looking for is non-static fields that belong to each individual instance. You also have to initialize these fields every time you make a new ball. static fields only get initialized once when the class is loaded. There are a couple more changes that I would recommend:
If your x- and y-coordinates belong only to the one ball, it is better to make them private.
Extend JComponent instead of Component, since you are clearly using swing here.
Implement paintComponent instead of draw. It will make your drawing code require less maintenance if nothing else.
Here is a version of the class that should work a bit better:
public class Ball extends JComponent
{
private double ballX;
private double ballY;
public static Ball[] balls = new Ball[20];
public Ball()
{
ballX = rand.nextInt(500) + 40;
ballY = rand.nextInt(300) + 10;
}
public void paintComponent(Graphics g2)
{
Color color = new Color(r, g, b);
g2.setColor(color);
g2.fillOval((int) ballX, (int) ballY, 30, 30);
}
}
Painting code is for painting only.
You should NEVER create/start a Timer in a painting method. Get rid of all that code.
You should never invoke repaint(), this will cause an infinite loop.
Also, get rid of all you animation code. Your first task is to paint multiple balls on the panel. Once you get this working, then you worry about trying to do animation.
There is no need to extend JComponent, since you class is NOT a component. That is you never add the component to a panel. All you do is paint the object in another class.
So your BallComponent class (which is a component) needs to have an ArrayList which keeps track of the ball objects you want to paint. So you need a method to add a ball object to this ArrayList. Then the paintComponent() method simply iterates through the list and paints all the balls.
Check out the DrawOnComponent example found in Custom Painting Approaches.
This question already has answers here:
How to change JFrame icon [duplicate]
(8 answers)
Closed 6 years ago.
How do I add an icon to this snake game and where do I put it, also how do I increase speed of the game after so many points? The code below is the class in which I believe these two pieces of code should go.
import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class SnakeGame extends JFrame {
private static final long FRAME_TIME = 1000L / 50L;
private static final int MIN_SNAKE_LENGTH = 5;
private static final int MAX_DIRECTIONS = 3;
private BoardPanel board;
private SidePanel side;
private Random random;
private Clock logicTimer;
private boolean isNewGame;
private boolean isGameOver;
private boolean isPaused;
private LinkedList<Point> snake;
private LinkedList<Direction> directions;
private int score;
private int foodsEaten;
private int nextFoodScore;
private SnakeGame() {
super("Snake");
setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
this.board = new BoardPanel(this);
this.side = new SidePanel(this);
add(board, BorderLayout.CENTER);
add(side, BorderLayout.EAST);
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_W:
case KeyEvent.VK_UP:
if(!isPaused && !isGameOver) {
if(directions.size() < MAX_DIRECTIONS) {
Direction last = directions.peekLast();
if(last != Direction.South && last != Direction.North) {
directions.addLast(Direction.North);
}
}
}
break;
case KeyEvent.VK_S:
case KeyEvent.VK_DOWN:
if(!isPaused && !isGameOver) {
if(directions.size() < MAX_DIRECTIONS) {
Direction last = directions.peekLast();
if(last != Direction.North && last != Direction.South) {
directions.addLast(Direction.South);
}
}
}
break;
case KeyEvent.VK_A:
case KeyEvent.VK_LEFT:
if(!isPaused && !isGameOver) {
if(directions.size() < MAX_DIRECTIONS) {
Direction last = directions.peekLast();
if(last != Direction.East && last != Direction.West) {
directions.addLast(Direction.West);
}
}
}
break;
case KeyEvent.VK_D:
case KeyEvent.VK_RIGHT:
if(!isPaused && !isGameOver) {
if(directions.size() < MAX_DIRECTIONS) {
Direction last = directions.peekLast();
if(last != Direction.West && last != Direction.East) {
directions.addLast(Direction.East);
}
}
}
break;
case KeyEvent.VK_P:
if(!isGameOver) {
isPaused = !isPaused;
logicTimer.setPaused(isPaused);
}
break;
case KeyEvent.VK_ENTER:
if(isNewGame || isGameOver) {
resetGame();
}
break;
}
}
});
pack();
setLocationRelativeTo(null);
setVisible(true);
}
private void startGame() {
this.random = new Random();
this.snake = new LinkedList<>();
this.directions = new LinkedList<>();
this.logicTimer = new Clock(10.0f);
//////////////////////////////////////////////////////////////////////////////////////////////////
this.isNewGame = true;
logicTimer.setPaused(true);
while(true) {
long start = System.nanoTime();
logicTimer.update();
if(logicTimer.hasElapsedCycle()) {
updateGame();
}
board.repaint();
side.repaint();
long delta = (System.nanoTime() - start) / 1000000L;
if(delta < FRAME_TIME) {
try {
Thread.sleep(FRAME_TIME - delta);
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
private void updateGame() {
TileType collision = updateSnake();
if(collision == TileType.Food) {
foodsEaten++;
score += nextFoodScore;
spawnFood();
} else if(collision == TileType.SnakeBody) {
isGameOver = true;
logicTimer.setPaused(true);
} else if(nextFoodScore > 10) {
}
}
private TileType updateSnake() {
Direction direction = directions.peekFirst();
Point head = new Point(snake.peekFirst());
switch(direction) {
case North:
head.y--;
break;
case South:
head.y++;
break;
case West:
head.x--;
break;
case East:
head.x++;
break;
}
if(head.x < 0 || head.x >= BoardPanel.COL_COUNT || head.y < 0 || head.y >= BoardPanel.ROW_COUNT) {
return TileType.SnakeBody;
}
TileType old = board.getTile(head.x, head.y);
if(old != TileType.Food && snake.size() > MIN_SNAKE_LENGTH) {
Point tail = snake.removeLast();
board.setTile(tail, null);
old = board.getTile(head.x, head.y);
}
if(old != TileType.SnakeBody) {
board.setTile(snake.peekFirst(), TileType.SnakeBody);
snake.push(head);
board.setTile(head, TileType.SnakeHead);
if(directions.size() > 1) {
directions.poll();
}
}
return old;
}
private void resetGame() {
this.score = 0;
this.foodsEaten = 0;
this.isNewGame = false;
this.isGameOver = false;
Point head = new Point(BoardPanel.COL_COUNT / 2, BoardPanel.ROW_COUNT / 2);
snake.clear();
snake.add(head);
board.clearBoard();
board.setTile(head, TileType.SnakeHead);
directions.clear();
directions.add(Direction.North);
logicTimer.reset();
spawnFood();
}
public boolean isNewGame() {
return isNewGame;
}
public boolean isGameOver() {
return isGameOver;
}
public boolean isPaused() {
return isPaused;
}
private void spawnFood() {
this.nextFoodScore = 10;
int index = random.nextInt(BoardPanel.COL_COUNT * BoardPanel.ROW_COUNT - snake.size());
int freeFound = -1;
for(int x = 0; x < BoardPanel.COL_COUNT; x++) {
for(int y = 0; y < BoardPanel.ROW_COUNT; y++) {
TileType type = board.getTile(x, y);
if(type == null || type == TileType.Food) {
if(++freeFound == index) {
board.setTile(x, y, TileType.Food);
break;
}
}
}
}
}
public int getScore() {
return score;
}
public int getFoodsEaten() {
return foodsEaten;
}
public int getNextFoodScore() {
return nextFoodScore;
}
public Direction getDirection() {
return directions.peek();
}
public static void main(String[] args) {
SnakeGame snake = new SnakeGame();
snake.startGame();
}
}
Create a new ImageIcon object like this:
ImageIcon img = new ImageIcon(pathToFileOnDisk);
Then set it to your JFrame with setIconImage():
myFrame.setIconImage(img.getImage());
Also checkout setIconImages() which takes a List instead.
How to change JFrame icon
It 's not my answer !!!!