Okay, so my question is, in swing, how could i make two of the same thing while they both have the same attributes but yet can act independently, for example, i am working on a city builder, when the uses presses a button to add a oil power station, the power station will get added to the world, however, there is only one. how could i make it so that the player could make a seamless amount of the same building but yet they all act independently, e.g when i go to add a second of the same building the first one won't follow the mouse.
heres my current code to help explain my issue:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class Game extends JFrame{
public Image map;
public Image utilButton;
public Image resButton;
public Image oilPlantBox;
public Image apartmentBlockABox;
//Building Img
public Image oilPowerStation;
public Image apartmentBlockA;
//Util selects
boolean showUtil = false;
boolean UtilSelect = false;
//Residential selects
boolean showRes = false;
boolean resSelect = false;
//Oil Power Station
boolean showOPPBox = true;
boolean checkOilPowerPlant = false;
boolean drawOilPlant = false;
boolean setPowerStation = false;
boolean placeOilPowerPlant = true;
int OilPowerStationxX = 0;
int OilPowerStationY = 0;
//Apartment Block A
boolean showABA = true;
boolean checkApartmentBlockA = false;
boolean drawApartmentBlockA = false;
boolean setApartmentBlockA = false;
boolean placeApartmentBlockA = true;
int apartmentBlockAX = 0;
int apartmentBlockAY = 0;
int x;
int y;
public int power = 0;
int jobs = 0;
public Game(){
//Load Images:
ImageIcon mapI = new ImageIcon("C:/Programs/Eclipse/eclipse/CityCenterBeta/bin/map.jpg");
map = mapI.getImage();
ImageIcon utilButtonI = new ImageIcon("C:/Programs/Eclipse/eclipse/CityCenterBeta/bin/UTIL.jpg");
utilButton = utilButtonI.getImage();
ImageIcon resButtonI = new ImageIcon("C:/Programs/Eclipse/eclipse/CityCenterBeta/bin/RES.jpg");
resButton = resButtonI.getImage();
ImageIcon oPB = new ImageIcon("C:/Programs/Eclipse/eclipse/CityCenterBeta/bin/oilPlantBox.png");
oilPlantBox = oPB.getImage();
ImageIcon aBAB = new ImageIcon("C:/Programs/Eclipse/eclipse/CityCenterBeta/bin/apartmentABlock.jpg");
apartmentBlockABox = aBAB.getImage();
//Building Images
//Oil Power Station
ImageIcon oilPlantI = new ImageIcon("C:/Programs/Eclipse/eclipse/CityCenterBeta/bin/oilPlant.jpg");
oilPowerStation = oilPlantI.getImage();
//Apartment Block A
ImageIcon apartmentBlockI = new ImageIcon("C:/Programs/Eclipse/eclipse/CityCenterBeta/bin/apartment block.jpg");
apartmentBlockA = apartmentBlockI.getImage();
//Set up game
addKeyListener(new AL());
addMouseListener(new Mouse());
init();
}
private Image dbImage;
private Graphics dbg;
public static void main(String[] args) {
new Game();
}
//When the program runs, thins are initialised here
public void init(){
windowManager();
}
public void paintComponent(Graphics g){
g.drawImage(map,0,0,null);
g.drawImage(utilButton,20,100,null);
g.drawImage(resButton,20,200,null);
if(showUtil == true){
if(showOPPBox == true){
g.drawImage(oilPlantBox,190,130,null);
}
}
if(showRes == true){
if(showABA == true){
g.drawImage(apartmentBlockABox,190,130,null);
}
}
if(drawOilPlant == true){
g.drawImage(oilPowerStation,OilPowerStationxX,OilPowerStationY,null);
if(checkOilPowerPlant == true){
setPowerStation = true;
}
if(drawApartmentBlockA == true){
g.drawImage(apartmentBlockA,apartmentBlockAX,apartmentBlockAY,null);
if(checkApartmentBlockA == true){
setApartmentBlockA = true;
}
}
}
repaint();
}
public void paint(Graphics g){
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage,0,0,this);
}
public void windowManager(){
JFrame f = new JFrame();
setTitle("City Center");
setVisible(true);
setResizable(false);
setBackground(Color.BLACK);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setExtendedState(f.MAXIMIZED_BOTH);
setUndecorated(true);
}
public class AL extends KeyAdapter{
public void keyPressed(KeyEvent e){
int keyCode = e.getKeyCode();
if(keyCode == e.VK_ENTER){
if(setPowerStation == true)
placeOilPowerPlant = false;
checkOilPowerPlant = false;
setPowerStation = false;
showUtil = false;
UtilSelect = false;
showOPPBox = false;
oilPlantAtt();
System.out.println(jobs + " Job Openings");
System.out.println(power + "MW");
}
if(setApartmentBlockA == true){
placeApartmentBlockA = false;
checkApartmentBlockA = false;
setApartmentBlockA = false;
showRes = false;
resSelect = false;
showABA = false;
apartmentBlockAtt();
}
}
public void keyReleased(KeyEvent e){
}
}
public class Mouse extends MouseAdapter {
public void mousePressed(MouseEvent e) {
x = e.getX();
y = e.getY();
//Pressed Utilies button
if((x > 20) && (x < 120) && (y > 100) && (y < 200) && (showUtil == false)) {
showUtil = true;
UtilSelect = true;
showRes = false;
resSelect = false;
}
//Pressed Residential Button
if((x > 20) && (x < 120) && (y > 200) && (y < 300) && (showRes == false)){
showRes = true;
resSelect = true;
showUtil = false;
UtilSelect = false;
}
if((x > 190) && (x < 265) && (y > 130) && (y < 192)){
if(resSelect == true){
drawApartmentBlockA = true;
if(placeApartmentBlockA == true){
checkApartmentBlockA = true;
}
}
if(UtilSelect == true){
drawOilPlant = true;
if(placeOilPoerPlant == true){
checkOilPowerPlant = true;
}
}
}
if(setPowerStation == true){
OilPowerStationxX = x;
OilPowerStationY = y;
}else{
OilPowerStationxX = OilPowerStationxX;
OilPowerStationY = OilPowerStationY;
}
if(setApartmentBlockA == true){
apartmentBlockAX = x;
apartmentBlockAY = y;
}else{
apartmentBlockAX = apartmentBlockAX;
apartmentBlockAY = apartmentBlockAY;
}
}
}
public void oilPlantAtt(){
jobs = jobs + 150;
power = power + 1000;
}
public void apartmentBlockAtt(){
boolean work = false;
if(power > 0){
work = true;
}
if(work == true){
jobs = jobs - 300;
power = power - 100;
}
}
You actually need to create 2 different instances with the similar properties or try this snippet:
Object building = new Object();
building.isLockedInPlace = false;
And use building.isLockedInPlace to say if you have one down.
To have multiple, you will have to use Object.clone();.
Hope it works and happy coding!
Based on your problem description and your provided code, it appears that you are new to object-oriented programming (OOP), which Java revolves around. If you haven't done so already, I'd recommend looking through the core Java tutorials again, regarding objects and their use.
As it stands, you have included everything in one file: the attributes of your power plant, of your apartment block, etc. What your program should look like is the following:
A Game class (which you have already) that contains either one or a collection of City objects.
A City class which contains a collection of Building objects.
A Building class could be abstract or an interface, which your ApartmentBlock and PowerPlant classes would extend or implement.
This structure is extensible and allows you to easily add more buildings and building types. You can also better enforce data encapsulation (which you aren't doing at all here), as each concrete building class (like your ApartmentBlock and PowerPlant) would also be the only ones who cared about what image they were displaying, and other data building specific information that only they really need to know.
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.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
Everybody!
I'm here to annoy you once more)
So, I was trying to make a game, I described some classes:
GameObject - just an object which has X,Y,Sizes,Name and may be drawn and moved:
package pkg3dgraphics;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
public class GameObject {
protected String name;
protected int xCoord,yCoord,mySizeX = 25,mySizeY = 25;
public GameObject(){
}
public GameObject(String newName, int startXCoord, int startYCoord){
setName(newName);
setX(startXCoord);
setY(startYCoord);
}
public void SetSize(int X, int Y){
mySizeX = X;
mySizeY = Y;
}
public int getXsize(){
return mySizeX;
}
public int getYsize(){
return mySizeY;
}
public String getName(){
return name;
}
public void setName(String newName){
name = newName;
}
public int getX(){
return xCoord;
}
public int getY(){
return yCoord;
}
public void setX(int newXCoord){
xCoord = newXCoord;
}
public void setY(int newYCoord){
yCoord = newYCoord;
}
public void moveTo(int X,int Y){
xCoord = X;
yCoord = Y;
}
public void moveBy(int X,int Y){
xCoord +=X;
yCoord +=Y;
}
public void Draw(GraphicsContext currentContext){
currentContext.setFill(Color.GREEN);
currentContext.setStroke(Color.BLUE);
currentContext.fillOval(xCoord,yCoord, mySizeX,mySizeY );
}
}
And I have Shooter extending previous class and here he goes:
package pkg3dgraphics;
public class Shooter extends GameObject {
public Shooter(){
}
public Shooter(String newName, int startXCoord, int startYCoord){
setName(newName);
setX(startXCoord);
setY(startYCoord);
}
public Bullet shoot(String direction){
Bullet newBullet = new Bullet(direction);
return newBullet;
}
}
Also I've got Bullets which are , you know, bullets:
package pkg3dgraphics;
import javafx.scene.paint.Color;
import javafx.scene.canvas.GraphicsContext;
public class Bullet extends GameObject{
String myDirection;
protected int mySpeed = 5,mySizeX = 5,mySizeY = 5;
boolean goNorth,goSouth,goWest,goEast;
protected boolean active = false;
public void setSpeed(int newSpeed){
mySpeed = newSpeed;
}
public void setDirection(String newDirection){
myDirection = newDirection;
active = true;
if ( myDirection == "North" )
goNorth = true;
if ( myDirection == "South" )
goSouth = true;
if ( myDirection == "West" )
goWest = true;
if ( myDirection == "East" )
goEast = true;
}
Bullet(String direction ){
myDirection = direction;
active = true;
if ( myDirection == "North" )
goNorth = true;
if ( myDirection == "South" )
goSouth = true;
if ( myDirection == "West" )
goWest = true;
if ( myDirection == "East" )
goEast = true;
}
public void advance(int W,int H,GraphicsContext gc){
if (xCoord <= W && xCoord >= 0 && yCoord <= H && yCoord >= 0 ) {
if (goNorth) moveBy(0,mySpeed);
if (goSouth) moveBy(0,mySpeed);
if (goWest) moveBy(mySpeed,0);
if (goEast) moveBy(mySpeed,0);
}else{
active = false;
Vanish(gc);
goNorth = false;
goSouth = false;
goWest = false;
goEast = false;
}
}
public void Vanish(GraphicsContext gc){
gc.setFill(Color.WHITE);
}
}
The purpose was to have this guy shooting in a next way:
When I catch pressed button I use precreated inactive bullet and direct it to go in a several direction.
When this bullet crosses a window's border it becomes inactive and stops.
For this I have an array of Bullets.
When user presses shoot key I seek in the array for an inactive Bullet and if there is none I create additional one which follows the path user wanted.
Well, this way to Implement bullets probably is not the best, but I didn't come up with another.
So I compiled my Main Class:
package pkg3dgraphics;
import java.util.Vector;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import static javafx.scene.input.KeyCode.DOWN;
import static javafx.scene.input.KeyCode.LEFT;
import static javafx.scene.input.KeyCode.RIGHT;
import static javafx.scene.input.KeyCode.SHIFT;
import static javafx.scene.input.KeyCode.UP;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
public int WINDOWWIDTH = 600;
public int WINDOWHEIGHT = 400;
boolean goNorth,goSouth,goWest,goEast,running,ShootNorth,ShootSouth,ShootWest,ShootEast;
Shooter player = new Shooter("Player",WINDOWWIDTH/2,WINDOWHEIGHT/2);
Bullet bullets[] = new Bullet[500];
int bulletsSize = 0;
Canvas mainCanvas = new Canvas(WINDOWWIDTH,WINDOWHEIGHT);
GraphicsContext mainContext = mainCanvas.getGraphicsContext2D();
#Override
public void start(Stage primaryStage) {
Group root = new Group();
Canvas mainCanvas = new Canvas(WINDOWWIDTH,WINDOWHEIGHT);
GraphicsContext mainContext = mainCanvas.getGraphicsContext2D();
root.getChildren().add(mainCanvas);
Scene scene = new Scene(root,WINDOWWIDTH,WINDOWHEIGHT);
scene.setOnKeyPressed(new EventHandler<KeyEvent> (){
#Override
public void handle(KeyEvent event){
switch(event.getCode()){
case UP: ShootNorth = true; break;
case DOWN: ShootSouth = true; break;
case LEFT: ShootWest = true; break;
case RIGHT: ShootEast = true; break;
case W: goNorth = true; break;
case S: goSouth = true; break;
case A: goWest = true; break;
case D: goEast = true; break;
}
}
});
scene.setOnKeyReleased(new EventHandler <KeyEvent>(){
#Override
public void handle(KeyEvent event){
switch(event.getCode()){
case UP: ShootNorth = false; break;
case DOWN: ShootSouth = false; break;
case LEFT: ShootWest = false; break;
case RIGHT: ShootEast = false; break;
case W: goNorth = false; break;
case S: goSouth = false; break;
case A: goWest = false; break;
case D: goEast = false; break;
}
}
});
primaryStage.setScene(scene);
primaryStage.show();
AnimationTimer Timer = new AnimationTimer(){
#Override
public void handle (long now){
int dx = 0, dy = 0;
if (goNorth) dy = -1;
if (goSouth) dy = 1;
if (goWest) dx = -1;
if (goEast) dx = 1;
if (running) { dx *= 3; dy *= 3;}
mainContext.clearRect(0,0,WINDOWWIDTH,WINDOWHEIGHT);
player.moveBy(dx, dy);
CheckShoot();
player.Draw(mainContext);
}
};
Timer.start();
}
public void CheckShoot(){
String direction = null;
int count = 0;
if (ShootNorth)
{
direction = "North";
}
if (ShootSouth)
{
direction = "South";
}
if (ShootWest)
{
direction = "West";
}
if (ShootEast)
{
direction = "East";
}
for (int i = 0; i < bulletsSize; i ++ )
{
if (bullets[i].active = false ){
bullets[i].setDirection(direction);
bullets[i].moveTo(player.getX(),player.getY());
break;
}else count ++;
}
if ( count == bulletsSize ) {
bulletsSize++;
bullets[bulletsSize] = player.shoot(direction);
}
}
public void advanceAll(){
for (int i = 0; i < bulletsSize; i ++ )
{
bullets[i].advance(WINDOWWIDTH,WINDOWHEIGHT,mainContext);
}
}
}
Application runs but then I get this problem looped untill I close the application:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at pkg3dgraphics.Main.CheckShoot(Main.java:126)
at pkg3dgraphics.Main$3.handle(Main.java:91)
at javafx.animation.AnimationTimer$AnimationTimerReceiver.lambda$handle$483(AnimationTimer.java:57)
at java.security.AccessController.doPrivileged(Native Method)
at javafx.animation.AnimationTimer$AnimationTimerReceiver.handle(AnimationTimer.java:56)
at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:357)
at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:506)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$403(QuantumToolkit.java:319)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
at java.lang.Thread.run(Thread.java:748)
So, that is all I wanted to complain about.
If someone has any idea why these all occure I would be glad and grateful if you shared the secret with me.(And all others)
You seem to have created the array, without creating each members
Bullet bullets[] = new Bullet[500];
Then you iterate through them, while they are nulls
for (int i = 0; i < bulletsSize; i ++ )
{
if (bullets[i].active = false ){
bullets[i].setDirection(direction);
bullets[i].moveTo(player.getX(),player.getY());
break;
}else count ++;
}
bullets[i] = null, and you try to invoke .active on it.
Solution:
Try to check nulls
if (bullets[i] == null) { bullets[i] = new Bullet(); }
if (bullets[i].active = false ){
bullets[i].setDirection(direction);
bullets[i].moveTo(player.getX(),player.getY());
break;
}else count ++;
Read What is NullPointerException
I'm making a game similar to feeding frenzy. I'm using mouseMotionListener to move a JLabel around a JFrame. At the same time, there are other JLabels that act as other fish to be eaten by the JLabel controlled by the mouse. Every time a JLabel fish (not controlled by mouse) moves in to and out of the screen, the JLabel controlled by the mouse returns back to a standard location on the screen, the center of the top half of the screen. What can I do to stop that from occurring?
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import sun.audio.*;
import java.io.*;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.event.MouseEvent;
public class playFishGame extends JPanel implements MouseMotionListener {
private JFrame board;// the main board
private JLabel fish;
private JLabel enemyFishS;
private JLabel enemyFishS2;
private JLabel enemyFishS3;
private ImageIcon fishPic;
private ImageIcon enemyFishSPic;
private ImageIcon winBackground;
private ImageIcon background;
private ImageIcon loseBackground;
ImageIcon fishSmall1r = new ImageIcon("data/fishSmall1r.png");
ImageIcon fishSmall1l = new ImageIcon("data/fishSmall1l.png");
ImageIcon fishSmall2r = new ImageIcon("data/fishSmall2r.png");
ImageIcon fishSmall2l = new ImageIcon("data/fishSmall2l.png");
ImageIcon fishSmall4r = new ImageIcon("data/fishSmall4r.png");
ImageIcon fishSmall4l = new ImageIcon("data/fishSmall4l.png");
private fish fishFish;
private fish enemyFishSFish;
private fish enemyFishSFish2;
private fish enemyFishSFish3;
private int origin;
private boolean contact, win;
Cursor blankCursor = null;
public static void main(String args[]) {
playFishGame play = new playFishGame();
}
public playFishGame() {
blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(
Toolkit.getDefaultToolkit().createImage("data/blank.png"),
new Point(0, 0), "blankCursor"); // blank.png is any tranparent
// image.
board = new JFrame("Play Fish Game");
board.setSize(1300, 700);
board.getContentPane().setCursor(blankCursor);
board.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
board.add(this);// adds JLabel to JFrame
this.addMouseMotionListener(this);
board.setVisible(true);
ImageIcon fishPic = new ImageIcon("data/sfr.gif");
fish = new JLabel(fishPic);
enemyFishS = new JLabel(" ");
enemyFishS2 = new JLabel(" ");
fishFish = new fish(617, 0);
enemyFishSFish = new fish(1300, 350);
enemyFishSFish2 = new fish(0, 500);
// enemyFishSFish3= new fish(1300,200);
this.add(fish);
this.add(enemyFishS);
this.add(enemyFishS2);
contact = false;
win = false;
repaint();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
if (enemyFishSFish.initiate == true) {
randomFishSmall(enemyFishSFish, enemyFishS);// picks image and
// starting
// point/side
enemyFishSFish.initiate = false;
}
if (enemyFishSFish.chooseSide == 0) {
enemyFishSFish.moveLeft();
if (enemyFishSFish.getX() < 5) {
enemyFishSFish.initiate = true;
}
} else if (enemyFishSFish.chooseSide == 1) {
enemyFishSFish.moveRight();
if (enemyFishSFish.getX() > 1295) {
enemyFishSFish.initiate = true;
}
}
if (enemyFishSFish2.initiate == true) {
randomFishSmall(enemyFishSFish2, enemyFishS2);// picks image and
// starting
// point/side
enemyFishSFish2.initiate = false;
}
if (enemyFishSFish2.chooseSide == 0) {
enemyFishSFish2.moveLeft();
if (enemyFishSFish2.getX() < 5) {
enemyFishSFish2.initiate = true;
}
} else if (enemyFishSFish2.chooseSide == 1) {
enemyFishSFish2.moveRight();
if (enemyFishSFish2.getX() > 1295) {
enemyFishSFish2.initiate = true;
}
}
enemyFishS.setLocation(enemyFishSFish.getX(), enemyFishSFish.getY());
contact(enemyFishSFish);
enemyFishS2.setLocation(enemyFishSFish2.getX(),
enemyFishSFish2.getY());
contact(enemyFishSFish2);
// contact(enemyFishSFish);
// enemyFishS2.setLocation(enemyFishSFish2.getX(),enemyFishSFish2.getY());
// enemyFishS3.setLocation(enemyFishSFish3.getX(),enemyFishSFish3.getY());
}
}, 0, 100);
board.setState(Frame.ICONIFIED);
board.setState(Frame.NORMAL);
}
public void mouseMoved(MouseEvent evt) {
System.out.println(evt.getPoint().x + ", " + evt.getPoint().y);
if ((evt.getPoint().x < 1231) && (evt.getPoint().y < 623)) {
fish.setLocation(evt.getPoint().x, evt.getPoint().y);
fishFish.override(evt.getPoint().x, evt.getPoint().y);
}
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
origin = fishFish.getX();
}
}, 0, 100);
int posneg = origin - evt.getPoint().x;
ImageIcon sfr = new ImageIcon("data/sfr.gif");
ImageIcon sfl = new ImageIcon("data/sfl.gif");
ImageIcon mfr = new ImageIcon("data/mfr.gif");
ImageIcon mfl = new ImageIcon("data/mfl.gif");
if (posneg < 0) {
if (fishFish.sFish < 10)
fish.setIcon(sfr);
if (fishFish.sFish > 9)
fish.setIcon(mfr);
}
if (posneg > 0) {
if (fishFish.sFish < 10)
fish.setIcon(sfl);
if (fishFish.sFish > 9)
fish.setIcon(mfl);
}
}
public void mouseDragged(MouseEvent evt) {
}
// 95/34
public void contact(fish enemyFish) {
if ((Math.abs(fishFish.getX() - enemyFish.getX())) < 48
&& (Math.abs(fishFish.getY() - enemyFish.getY()) < 36)
&& (fishFish.sFish < 10)) {
fishFish.sFish++;
enemyFish.initiate = true;
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
background = new ImageIcon("data/background3.png");
winBackground = new ImageIcon("data/");
loseBackground = new ImageIcon("data/");
if ((contact == false) && (win == false))
g.drawImage(background.getImage(), 0, 0, null);
if (contact == true)
g.drawImage(loseBackground.getImage(), 0, 0, null);
if (win == true)
g.drawImage(winBackground.getImage(), 0, 0, null);
}
public void randomFishSmall(fish changeFishFish, JLabel changeFish) {
int chooseType = (int) (Math.random() * 3);
// int chooseType=2;
int chooseSide = (int) (Math.random() * 2);// left=0right=1
int chooseSpeed = (int) (Math.random() * 12) + 6;
int choosePlacement = (int) (Math.random() * 1288) + 15;
changeFishFish.chooseType = chooseType;
changeFishFish.chooseSide = chooseSide;
changeFishFish.chooseSpeed = chooseSpeed;
changeFishFish.choosePlacement = choosePlacement;
if (chooseType == 0) {
if (chooseSide == 0) {
changeFish.setIcon(fishSmall1l);
changeFishFish.override(1300, choosePlacement);
// changeFishFish.
} else {
changeFish.setIcon(fishSmall1r);
changeFishFish.override(0, choosePlacement);
}
changeFish.setLocation(changeFishFish.getX(), changeFishFish.getY());
} else if (chooseType == 1) {
if (chooseSide == 0) {
changeFish.setIcon(fishSmall2l);
changeFishFish.override(1300, choosePlacement);
} else {
changeFish.setIcon(fishSmall2r);
changeFishFish.override(0, choosePlacement);
}
changeFish.setLocation(changeFishFish.getX(), changeFishFish.getY());
} else if (chooseType == 2) {
if (chooseSide == 0) {
changeFish.setIcon(fishSmall4l);
changeFishFish.override(1300, choosePlacement);
// changeFishFish.
} else {
changeFish.setIcon(fishSmall4r);
changeFishFish.override(0, choosePlacement);
}
changeFish.setLocation(changeFishFish.getX(), changeFishFish.getY());
}
}
}
First of all:
Class names start with an upper case character. Learn by example. Just look at the Java API and you will see all class names start with an upper case character.
Don't do I/O in a painting method. Painting methods are called whenever Swing determines a component needs to be repainted. It is not efficient to read files every time. Read the images when the class is created.
Don't hardcode the size of the frame - board.setSize(1300, 700); Not everybody uses the same resolution. To maximize the frame you can use: board.setExtendedState(JFrame.MAXIMIZED_BOTH);
returns back to a standard location on the screen, the center of the top half of the screen
By default a JPanel uses a FlowLayout. When you change the location of the other labels the layout manager is invoked to components a place in the position determined by the layout manager.
If you have random placement of a component because you are using the mouse to drag the component, then you need to use a "null layout" on the panel. When you do this you are now responsible for manually setting the "size and location" of every component you add to the panel.
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.