I asked this same question a while ago, and i was told to initialize my squareChecker variable and so i did. I still get the same error for some reason that i am unaware of. I have spent literally all day trying to figure out this problem by myself, but to no avail. Anybody know what my problem is?
My Normal Mode class (where i'm calling methods from square class and rendering things):
public class NormalMode extends BasicGameState {
private Square[][] square = new Square[4][4];
private Square squareChecker;
Graphics g;
public NormalMode() { }
#Override
public void init(GameContainer arg0, StateBasedGame Game)throws SlickException {
squareChecker = new Square(arg0);
squareChecker.startGame(g);
for(int i = 0; i < square.length; i++){
for(int j = 0; j < square.length; j++){
square[i][j] = new Square(arg0);
square[i][j].createRandom();
}
}
}
#Override
public void render(GameContainer container, StateBasedGame game, Graphics g)
throws SlickException{
square[0][0].squareDraw(100, 300, g);
square[0][1].squareDraw(150, 300, g);
square[0][2].squareDraw(200, 300, g);
square[0][3].squareDraw(250, 300, g);
square[1][0].squareDraw(100, 400, g);
square[1][1].squareDraw(150, 400, g);
square[1][2].squareDraw(200, 400, g);
square[1][3].squareDraw(250, 400, g);
square[2][0].squareDraw(100, 500, g);
square[2][1].squareDraw(150, 500, g);
square[2][2].squareDraw(200, 500, g);
square[2][3].squareDraw(250, 500, g);
square[3][0].squareDraw(100, 600, g);
square[3][1].squareDraw(150, 600, g);
square[3][2].squareDraw(200, 600, g);
square[3][3].squareDraw(250, 600, g);
}
#Override
public void update(GameContainer container, StateBasedGame game, int delta)
throws SlickException { }
#Override
public int getID() {
return 3;
}
}
My Square Class:
public class Square {
private StateBasedGame game;
boolean correct;
boolean clickable;
boolean clicked;
boolean started;
int squares;
int squareX;
int squareY;
public Image squareIncorrect;
public Image squareCorrect;
//For drawing these images from other classes
{
try {
squareIncorrect = new Image("res/squareIncorrect.png");
} catch (SlickException e1) {
e1.printStackTrace();
}
try {
squareCorrect = new Image("res/squareCorrect.png");
} catch (SlickException e) {
e.printStackTrace();
}
}
public Square(GameContainer container) { }
public boolean checkCorrect(){
return correct;
}
public boolean checkClickable(){
return clickable;
}
public boolean checkClicked(){
return clicked;
}
public int returnNumberOfSquares(){
return squares;
}
//Draw appropriate square on screen depending on the creatRandom. CREATE THE RANDOM FIRST!
public void squareDraw(int x ,int y, Graphics g)throws SlickException{
if(correct == true){
g.drawImage(squareCorrect, x, y);
started = true;
}
else if(correct == false){
g.drawImage(squareIncorrect, x, y);
started = true;
}
}
public void createRandom(){
Random rand = new Random();
int sRand = rand.nextInt(2);
if(sRand == 0){
correct = false;
clickable = true;
clicked = false;
System.out.println("This square is a phony!");
}
else if(sRand == 1){
correct = true;
clickable = true;
clicked = false;
System.out.println("This is a true Square!");
squares = squares+1;
}
}
public void youWin(int x, int y, Graphics g){
if(squares == 0){
g.drawString("You win!", x, y);
try {
wait(4000);
game.enterState(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void startGame(Graphics g){
g.drawString("Remember the blue squares! The game will start in 5 seconds!", 200, 300);
}
}
This is the error i get:
Exception in thread "main" java.lang.NullPointerException
at data.src.Square.startGame(Square.java:112)
at data.src.NormalMode.init(NormalMode.java:23)
at org.newdawn.slick.state.StateBasedGame.init(StateBasedGame.java:171)
at org.newdawn.slick.ScalableGame.init(ScalableGame.java:69)
at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:393)
at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:317)
at data.src.Core.main(Core.java:30)
In NormalMode.Init() you call squareChecker.startGame(g);
g is defined as Graphics g;.
startGame() calls g.drawString().
This leads me to conclude that you don't instantiate g prior to passing it to your startGame() method.
Related
I am coding a Java pong game I am stuck on how to get the player paddle to move. I for some reason cannot get the program to notice the key inputs.
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Pong {
Board board = new Board();
public void frame() {
JFrame b = new JFrame("Pong");
b.setSize(905,705);
b.setLocation(300,60);
b.setResizable(false);
b.setVisible(true);
b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b.add(board);
}
public static void main(String[] args) {
Pong start = new Pong();
start.frame();
}
}
The board class
public class Board extends JPanel{
public int playerScore = 0;
public int opponentScore = 0;
Player player = new Player();
int test = 1;
private Timer timer;
private int time = 100;{
timer = new Timer(time, player);
timer.start();
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
board(g);
g.setColor(Color.WHITE);
// player.playerGenerate();
g2d.fill(player.player);
g.fillRect(30, test, 20, 20);
player.paint(g);
control();
//repaint();
}
public void board(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g.setColor(Color.black);
g.fillRect(0, 0, 900, 900);
Stroke stroke1 = new BasicStroke(4f);
g2d.setColor(Color.white);
g2d.setStroke(stroke1);
g2d.drawRect(20, 50, 850, 600);
g2d.setColor(Color.white);
float[] dashingPattern2 = {10f, 4f};
Stroke stroke2 = new BasicStroke(4f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER, 1.0f, dashingPattern2, 0.0f);
g2d.setStroke(stroke2);
g2d.drawLine(435, 50, 435, 650);
g.setFont(new Font("arial",Font.PLAIN,30));
g.drawString(""+playerScore, 20, 35);
g.drawString(""+opponentScore, 855, 35);
}
public void control() {
if (player.down == true) {
player.playerYpos = player.playerYpos = player.playerYpos -10;
repaint();
}
}
}
And finally the player class.
public class Player extends JPanel implements KeyListener,ActionListener{
//Board theBoard = new Board();
public boolean down = false;
public boolean up = false;
public int playerXpos = 45;
public int playerYpos = 300;
public int playerWidth = 15;
public int playerHeight = 80;
Rectangle player = new Rectangle(playerXpos,playerYpos,playerWidth,playerHeight);
// Board theBoard = new Board();
public void playerGenerate() {
playerXpos = 45;
playerYpos = 300;
playerWidth = 15;
playerHeight = 80;
//Rectangle r = new Rectangle(playerXpos,playerYpos,playerWidth,playerHeight);
}
#Override
public void actionPerformed(ActionEvent e) {
if (down) {
down = true;
if(up != true) {
down = true;
}
else
{
up = true;
down = false;
}
}
if (up) {
up = true;
if(down != true) {
up = true;
}
else
{
up = false;
down = true;
}
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP) {
for(int r = playerYpos;r >=0;r--) {
if(r==0) {
playerYpos = playerYpos -20;
}
else {
playerYpos = playerYpos -1 ;
}
if(playerYpos < 50){
playerYpos = 50;
}
}
//repaint();
}
if(e.getKeyCode() == KeyEvent.VK_DOWN) {
for(int r = playerYpos;r >=0;r--) {
if(r==0) {
playerYpos = playerYpos +20;
}
else {
playerYpos = playerYpos -1 ;
System.out.print("down");
}
if(playerYpos > 800){
playerYpos = 800;
}
}
//repaint();
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
I tried googling around and looked at code that went with a similar approach of implementing action/key listener in the player/paddle class. I assume there is something minor and small I am just not seeing.
You have just wrote the method names. You need to register action/key listener to a particular swing component which you want to listen.
Suppose if your JComponent is JButton named btnPlayer you need to register the action performed event like :
private void btnPlayerActionPerformed(java.awt.event.ActionEvent e) {....
...}
You can add action listener from swing design. Right click on the JComponent -> Events -> ActionPerformed.
It will register click event for the component. Adding events through the properties is a better option.
I have an application, in which a car is moving on a panel and it creates sound waves - circles. I want to :
1) have a few circles at the moment of opening the frame
2) when the Start button is selected I want them to move and I want more circles to be created, one after another, until the stop button is selected
the problem is:
1) when the frame is opened there are 5 circles, but they totally do not move
2) 5 new circles appears, but from the same XY position, they are just bigger - I want one circle after another, it grows, and next one appears
here is my code, I would appreciate some helpful sample or could you tell me where my mistake is. I used amount of 5 just to have some samples of waves.
public class WaveParameters {
int xPos=0;
int yPos = 375;
int width=60;
int height=60;
int velX = 0 ;
private Color color = Color.WHITE;
public int getVelX() {
return velX;
}
public void setVelX(int velX) {
this.velX = velX;
}
public int getX() {
return xPos;
}
public void setX(int xPos) {
this.xPos = xPos;
}
public int getWidth(){
return width;}
public int getHeight(){
return height;}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public void paint(Graphics g){
g.setColor(getColor());
g.drawOval(xPos,yPos,width/2,height/2);
}
}
Here is the panel of animation:
public class PanelAnimation extends JPanel implements ActionListener{
List<WaveParameters> waves = new ArrayList<WaveParameters>();
public PanelAnimation(ResourceBundle bundle) {
super();
resourceBundle = bundle;
t.start();
try {
imageBackground = ImageIO.read(newFile("bg.png"));
} catch (IOException ex) {
// handle exception...
}
}
CarParametrs pAuto = new CarParametrs();
HumanParametrs pHuman = new HumanParametrs() ;
Timer t = new Timer(60,this);
//WaveParameters pWave = new WaveParameters();
private BufferedImage imageBackground;
MainFrame mf;
public void addAuto(){
CarParametrs ap = new CarParametrs();
ap.setX(0);
pAuto = ap;
}
public void addHuman(){
HumanParametrs acz = new HumanParametrs();
acz.setX(0);
pHuman = acz;
}
public void addWave() {
for (int i=0; i<5; i++) {
WaveParameters wave = new WaveParameters();
// wave.setX(pAuto.xPos);
wave.setColor(Color.white);
wave.setWidth(wave.width*i);
wave.setHeight(wave.height*i);
waves.add(wave);
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(imageBackground, 0, 0, null);
pAuto.paint(g);
pHuman.paint(g);
//if(mf.buttonStart.isSelected()) {
addWave();
//for (int i=0; i<5; i++) {
for (WaveParameters w : waves) {
// waves.add(new WaveParameters());
w.setX(pAuto.xPos);
w.paint(g);
//}
}
//}
}
public void actionPerformed(ActionEvent e) {
CarParametrs pa = pAuto;
pa.xPos += pa.velX;
/*//WaveParameters wp = pWave;
wp.xPos = pa.xPos;
wp.xPos+=wp.velX;
wp.height+=wp.velX;
wp.width+=wp.velX;
wp.yPos-=wp.velX/5 ;*/
for (WaveParameters w : waves) {
w.xPos = pa.xPos;
w.xPos+=w.velX;
w.height+=w.velX;
w.width+=w.velX;
w.yPos-=w.velX/5 ;
}
repaint();
}
and here is a wave-part of action listener for Start Button:
List<WaveParameters> wave = panelAnimation.waves;
for (WaveParameters w : wave) {
for (int i=0;i<5;i++) {
wave.add(new WaveParameters());
w.velX = Integer.parseInt(button2.getName());
w.xPos += w.velX;
w.width++;
w.height++;
w.yPos-=w.velX/5;
}
}
panelAnimation.repaint();
The five new bigger circles that appear are likely due to the last chunk of code where you iterate through all the waves in panel animation.
The "wave.add(new WaveParameters());" seems unnecessary, and may be the reason why your old waves are staying. Delete that line, and it may work.
My question is how can i implement the MouseMotionListener for list of objects can follow my mouse? I guess, I couldn't get the idea so far. I tried to do that my second part of the worm will follow the head. So it will become like a train. But in first second seems like Ok but all objects suddenly converge to a point.
Basically my code is above;
My Worm.class is like that;
public class Worm {
Random rd = new Random();
int xWorm;
int yWorm;
int Speed = 100;
int size = 10; // default
Worm()
{
xWorm = rd.nextInt(250);
yWorm = rd.nextInt(250);
}
Worm(int xNew, int yNew){
xWorm = xNew;
yWorm = yNew;
}
public int getxWorm() {
return xWorm;
}
public void setxWorm(int xWorm) {
this.xWorm = xWorm;
}
public int getyWorm() {
return yWorm;
}
public void setyWorm(int yWorm) {
this.yWorm = yWorm;
}
public int getSpeed() {
return Speed;
}
public void setSpeed(int speed) {
Speed = speed;
}
public void move (int dx, int dy) {
xWorm+=dx;
yWorm+=dy;
}
public void setPosition(int x,int y) {
this.xWorm = x;
this.yWorm = y;
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Ellipse2D Ellipse= new Ellipse2D.Double(xWorm,yWorm,10,10);
g2.setColor(Color.GREEN);
g2.draw(Ellipse);
g2.fill(Ellipse);
// g.fillOval(this.xWorm, this.yWorm, 30, 30);
}
public boolean iscollision(Food f) {
Rectangle2D RectangleforFood = new Rectangle2D.Double(f.xFood,f.yFood,5,5);
Rectangle2D RectangleforWormHead = new Rectangle2D.Double(this.xWorm,this.yWorm,10,10);
if (RectangleforWormHead.intersects(RectangleforFood)) {
return true;
}
else {
return false;
}
}
}
and my Panel.class the tracker function like that ;
public void createlongworm() {
for(int i = 0; i < 100 ; i++) {
wormBody.add(new Worm(wormBody.get(i).xWorm+10,wormBody.get(i).yWorm));
}}
public void tracker(ArrayList <Worm> TracktheWorm) {
for(int i = 0; i < TracktheWorm.size()-1 ; i++) {
TracktheWorm.get(i+1).xWorm = TracktheWorm.get(i).xWorm;
TracktheWorm.get(i+1).yWorm = TracktheWorm.get(i).yWorm;
}
repaint();
}
I am creating a Space Invaders Game with just one Invader. The images are stuttering and are only visible ~10% of the time. What is wrong with my code?
package spaceinvader;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class spaceInvaders extends JApplet implements KeyListener, ActionListener
{
//Declare components and variables
JPanel mainPanel = new JPanel();
ImageIcon carImage = new ImageIcon("ship.png");
ImageIcon invaderImage = new ImageIcon("invader.png");
int intPosX = 240;
int intPosY = 330;
int intXAmount = 15;
boolean shipMoveLeft = false;
boolean shipMoveRight = false;
Timer shipTimer = new Timer(100,this);
int intBulletX = -50;
int intBulletY = -50;
boolean bulletMove = false;
boolean bulletActive = false;
Timer bulletTimer = new Timer(50,this);
int intInvaderX = 0;
int intInvaderY = 0;
int invaderXAmount = 10;
boolean invaderMove = true;
Timer invaderTimer= new Timer(1000,this);
public void init()
{
addKeyListener(this);
setFocusable(true);
resize(600,400);
setContentPane(mainPanel);
shipTimer.start();
bulletTimer.start();
invaderTimer.start();
}
public void actionPerformed(ActionEvent e)
{
requestFocus();
if(shipMoveLeft)
intPosX += intXAmount;
else if(shipMoveRight)
intPosX -= intXAmount;
if(bulletMove && bulletActive){
intBulletY -= 15;
if(intBulletY <= -50){
bulletMove = false;
bulletActive = false;
}
}
if(invaderMove){
intInvaderX += invaderXAmount;
if(intInvaderX > getWidth() - 60 || intInvaderX < 0){
intInvaderY += 40;
invaderXAmount *= -1;
}
}
repaint();
}
public void keyPressed(KeyEvent e)
{
int key = e.getKeyCode();
if (key == 37){
shipMoveRight = true;
}
else if (key == 39){
shipMoveLeft = true;
}
else if (key == 32){
if(bulletActive == false){
intBulletX = intPosX;
intBulletY = intPosY;
}
bulletMove = true;
bulletActive = true;
}
}
public void keyReleased(KeyEvent e)
{
shipMoveLeft = false;
shipMoveRight = false;
}
public void keyTyped(KeyEvent e)
{
}
public void paint(Graphics gr)
{
super.paint(gr);
gr.setColor(Color.red);
gr.fillOval(intBulletX, intBulletY, 10, 25);
carImage.paintIcon(this,gr, intPosX, intPosY); //Draw image in new spot
invaderImage.paintIcon(this,gr, intInvaderX, intInvaderY);
}
}
So there are a number of issues which jump out immediately...
Applets are a dead end, most browsers will actively block them and/or have dropped support for the plugin
You're adding a JPanel to the applet, but overriding the applet's paint method, because of the way painting can work, the panel can be painted independently of the applet, causing it to paint over whatever you might have painted
You don't need multiple timers, you just need to have better delta values (smaller been faster)
KeyListener is a poor choice for detecting keyboard input, it's rather low level and has focus related issues which are easily overcome by using the Key Bindings API
I'd start by having a look at Performing Custom Painting, Painting in AWT and Swing and How to Use Key Bindings for more details.
So how would you start fixing it? Start by using a JPanel as you basic container, override it's paintComponent and place all your paint logic here.
Use a single Timer to manage the updates
There are any number of approaches you can take, but I'd start with defining some contracts that define what can go on in the game
public interface GameSpace extends ImageObserver {
public Dimension getGameSpace();
public boolean hasInput(Input input);
}
public interface Entity {
public void paint(GameSpace gameSpace, Graphics2D g2d);
public boolean update(GameSpace gameSpace);
public Rectangle getBounds();
}
public abstract class AbstractEntity implements Entity {
private int x;
private int y;
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
protected abstract int getWidth();
protected abstract int getHeight();
public Rectangle getBounds() {
return new Rectangle(getX(), getY(), getWidth(), getHeight());
}
}
public abstract class AbstractImageEntity extends AbstractEntity {
protected abstract BufferedImage getImage();
#Override
protected int getWidth() {
return getImage().getWidth();
}
#Override
protected int getHeight() {
return getImage().getHeight();
}
}
This separates some of management of key elements, allowing for a more flexible design. You might have a lot more entities, one's which could move, ones which could not, some which are painted, some which are not, but all which provide support for the core engine to get work done.
Once you have that you can start defining some core entities you need
public class ShipEntity extends AbstractImageEntity {
private BufferedImage ship;
public ShipEntity(GameSpace gameSpace) throws IOException {
ship = ImageIO.read(getClass().getResource("/resources/ship.png"));
setY(gameSpace.getGameSpace().height - getBounds().height);
setX((gameSpace.getGameSpace().width - getBounds().width) / 2);
}
#Override
public BufferedImage getImage() {
return ship;
}
#Override
public void paint(GameSpace gameSpace, Graphics2D g2d) {
g2d.drawImage(ship, getX(), getY(), gameSpace);
}
#Override
public boolean update(GameSpace gameSpace) {
int x = getX();
if (gameSpace.hasInput(Input.LEFT)) {
x -= 2;
}
if (gameSpace.hasInput(Input.RIGHT)) {
x += 2;
}
if (x < 0) {
x = 0;
} else if (x + getWidth() > gameSpace.getGameSpace().width) {
x = gameSpace.getGameSpace().width - getWidth();
}
setX(x);
return true;
}
}
public class InvaderEntity extends AbstractImageEntity {
private BufferedImage invader;
public InvaderEntity() throws IOException {
invader = ImageIO.read(getClass().getResource("/resources/Invader.png"));
}
#Override
protected BufferedImage getImage() {
return invader;
}
#Override
public void paint(GameSpace gameSpace, Graphics2D g2d) {
g2d.drawImage(invader, getX(), getY(), gameSpace);
}
#Override
public boolean update(GameSpace gameSpace) {
return true;
}
}
public class ProjectileEntity extends AbstractEntity {
private int delta;
public ProjectileEntity(int delta) {
this.delta = delta;
}
#Override
protected int getWidth() {
return 10;
}
#Override
protected int getHeight() {
return 10;
}
#Override
public void paint(GameSpace gameSpace, Graphics2D g2d) {
g2d.setColor(Color.RED);
int width = getWidth();
int height = getHeight();
g2d.fillOval(getX() - width / 2, getY() - height / 2, width, height);
}
#Override
public boolean update(GameSpace gameSpace) {
int y = getY() + delta;
setY(getY() + delta);
return y + getHeight() >= 0 && y + getHeight() <= gameSpace.getGameSpace().height;
}
}
Basically, they contain the logic required for getting their jobs done.
Finally, you need to setup the actual game UI
public class GamePane extends JPanel implements GameSpace {
private Set<Input> inputs;
private Entity playerEntity;
private List<Entity> projectileEntities;
private List<Entity> invaderEntities;
private long timeOfLastProjectile = -1;
public GamePane() throws IOException {
setBackground(Color.BLACK);
inputs = new HashSet<>(2);
playerEntity = new ShipEntity(this);
projectileEntities = new ArrayList<>(25);
invaderEntities = new ArrayList<>(25);
InvaderEntity invader = new InvaderEntity();
invader.setX((getGameSpace().width - invader.getBounds().width) / 2);
invader.setY((getGameSpace().height - invader.getBounds().height) / 2);
invaderEntities.add(invader);
addKeyBinding(Input.LEFT, "left", KeyEvent.VK_LEFT);
addKeyBinding(Input.RIGHT, "right", KeyEvent.VK_RIGHT);
addKeyBinding(Input.SPACE, "space", KeyEvent.VK_SPACE);
Timer timer = new Timer(15, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updateState();
processCollisions();
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
protected void updateState() {
playerEntity.update(this);
if (hasInput(Input.SPACE)) {
long time = System.currentTimeMillis() - timeOfLastProjectile;
if (time < 0 || time > 1000) {
timeOfLastProjectile = System.currentTimeMillis();
Rectangle bounds = playerEntity.getBounds();
ProjectileEntity projectile = new ProjectileEntity(-1);
int x = bounds.x + ((bounds.width - projectile.getWidth()) / 2);
int y = bounds.y - projectile.getHeight();
projectile.setX(x);
projectile.setY(y);
projectileEntities.add(projectile);
}
}
for (Entity entity : invaderEntities) {
entity.update(this);
}
List<Entity> outOfBounds = new ArrayList<>(25);
for (Entity entity : projectileEntities) {
if (!entity.update(this)) {
outOfBounds.add(entity);
}
}
projectileEntities.removeAll(outOfBounds);
}
protected void processCollisions() {
Set<Entity> hitInvaders = new HashSet<>(25);
Set<Entity> hitProjectiles = new HashSet<>(25);
for (Entity invader : invaderEntities) {
for (Entity projectile : projectileEntities) {
if (projectile.getBounds().intersects(invader.getBounds())) {
// Maybe lots of cool explosiions
hitInvaders.add(invader);
hitProjectiles.add(projectile);
}
}
}
invaderEntities.removeAll(hitInvaders);
projectileEntities.removeAll(hitProjectiles);
}
protected void addKeyBinding(Input input, String name, int virtualKey) {
ActionMap am = getActionMap();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(virtualKey, 0, false), name + ".pressed");
im.put(KeyStroke.getKeyStroke(virtualKey, 0, true), name + ".released");
am.put(name + ".pressed", new KeyAction(inputs, input, true));
am.put(name + ".released", new KeyAction(inputs, input, false));
}
#Override
public Dimension getGameSpace() {
return getPreferredSize();
}
#Override
public boolean hasInput(Input input) {
return inputs.contains(input);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
playerEntity.paint(this, g2d);
g2d.dispose();
for (Entity entity : invaderEntities) {
g2d = (Graphics2D) g.create();
entity.paint(this, g2d);
g2d.dispose();
}
for (Entity entity : projectileEntities) {
g2d = (Graphics2D) g.create();
entity.paint(this, g2d);
g2d.dispose();
}
}
}
public class KeyAction extends AbstractAction {
private Input input;
private Set<Input> inputs;
private boolean pressed;
public KeyAction(Set<Input> inputs, Input input, boolean pressed) {
this.input = input;
this.inputs = inputs;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
inputs.add(input);
} else {
inputs.remove(input);
}
}
}
Now you could go a little further and generate an "engine" class which controls the entities and performs all the required updating, but I'm lazy ;)
That's a really rough idea of some the basic concepts you need to develop to be able to move forward, hope it helps
Basically, all that shows up is a JFrame with the black JPanel inside but no Ball/polygon anywhere. It's really annoying me now and I can't see the reason why. Any help greatly appreciated.
EDIT: Added code. Sorry for posting to Github, didn't know it was frowned upon.
public class Board extends JFrame {
private int width = 800;
private int height = 1000;
private int currentKeyCode = 0;
private boolean keyHeldDown = false;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
Board b = new Board();
b.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Board() {
setSize(width, height);
setTitle("Drop");
setBackground(Color.BLACK);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
currentKeyCode = KeyEvent.VK_RIGHT;
keyHeldDown = true;
System.out.println("Right + 10");
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
currentKeyCode = KeyEvent.VK_LEFT;
keyHeldDown = true;
System.out.println("Left + 10");
}
if (e.getKeyCode() == KeyEvent.VK_P) {
currentKeyCode = KeyEvent.VK_P;
keyHeldDown = true;
System.out.println("Pause");
}
}
#Override
public void keyReleased(KeyEvent e) {
keyHeldDown = false;
}
});
setContentPane(new Panel(this));
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);
executor.scheduleAtFixedRate(new RepaintBoard(this), 0L, 20L, TimeUnit.MILLISECONDS);
}
#Override
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
#Override
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
private class RepaintBoard implements Runnable {
final Board board;
public RepaintBoard(Board board) {
this.board = board;
}
#Override
public void run() {
board.repaint();
}
}
}
class Panel extends JComponent {
Ball ball;
private Board board;
public Panel(Board board) {
this.board = board;
ball = new Ball();
}
#Override
public void paint(Graphics g1) {
Graphics2D g = (Graphics2D) g1;
g.setColor(Color.BLACK);
g.drawRect(0, 0, board.getWidth(), board.getHeight());
g.drawPolygon(ball);
}
}
class Ball extends Polygon {
private int radius = 5;
private Point loc;
private int[] xPos = new int[radius * 2 + 1];
private int[] yPos = new int[radius * 2 + 1];
public Ball() {
for (int i = -radius, j = 0; i <= radius; i++, j++) {
xPos[j] = i;
yPos[j] = i;
}
new Ball(xPos, yPos, radius * 2 + 1, 100, 100);
}
public Ball(int[] xPos, int[] yPos, int points, int x, int y) {
super(xPos, yPos, points);
loc = new Point(x, y);
for (int i : xPos) {
System.out.println(i);
}
}
}
Don't have Ball extends Polygon
Put a drawBall(Grapchics g) {} method in the Ball class, and do your ball painting in there.
call the drawBall method in the paint
ball.drawBall(g);
Don't override paint, instead override paintComponent on the panel, and don't forget to call super.paintComponent
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
This new Ball(xPos, yPos, radius * 2 + 1, 100, 100); in your constructor does absolutely nothing. You should instead just use the second constructor, and create the ball with that constructor. Each ball should be different, so a no-arg constructor is pointless