Trouble with drawing a moving paddle for pong flawlessly using Netbeans - java

I am trying to make Pong. I sent this program to a friend and when he ran it the first time he got my bug but later it ran fine. I always seem to get the bug. My paddle can move up and down. It seems to move correctly and it gets drawn in the right place but it always flickers to the start position and back again. It looks like it gets drawn once at the start position and then at the right positions, flickering between the 2 positions forever.
NetBeans complains about this.addKeyListener(this);. It says "Leaking this in constructor". Here is my code: (sorry in advance, first time posting)
I exported it from netbeans if anyone wants to take a look:
http://s000.tinyupload.com/?file_id=00856291054786890080
public class LeikGluggi extends javax.swing.JPanel implements ActionListener, KeyListener {
Spilari1 spilari1 = new Spilari1();//make paddle
Bolti bolti = new Bolti(); //make ball
public LeikGluggi() {
initComponents();
setSize(Leikbord.GLUGGI_BREIDD,Leikbord.GLUGGI_HAED);
this.addKeyListener(this);
this.setFocusable(true);
int i = 0;
Timer tim = new Timer(50, this);
tim.start();
}
private void uppfaera()//update
{
spilari1.uppfaera();//paddle update
bolti.uppfaera(); // ball update
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);//
g.setColor(Color.WHITE);
g.fillRect(0,0,Leikbord.GLUGGI_BREIDD,Leikbord.GLUGGI_HAED); //background
g.setColor(Color.BLUE);
spilari1.paint(g); //paddle drawn
bolti.paint(g); //ball drawn
}
#Override
public void actionPerformed(ActionEvent e)
{
uppfaera();//update called
repaint();
}
#Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_UP)
{
spilari1.setyHradi(-4);
}
else if (e.getKeyCode() == KeyEvent.VK_DOWN)
{
spilari1.setyHradi(4);
}
}
#Override
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_UP)
{
spilari1.setyHradi(0);
}
if (e.getKeyCode() == KeyEvent.VK_DOWN)
{
spilari1.setyHradi(0);
}
}
public void keyTyped(KeyEvent e)
{
}
And the code for my paddle
package is.hi.vidmotsforritun.pong2.teikning;
import java.awt.Color;
import java.awt.Graphics;
public class Spilari1 {
private final int breidd = 10 ;
private final int lengd = 75;
private int y = (Leikbord.GLUGGI_HAED/2)-lengd/2;
private int yHradi = 0;
public Spilari1()
{
}
public void uppfaera()
{
y = y + yHradi;
System.out.println("HRAÐI ER "+yHradi);
}
public void paint(Graphics g)
{
g.setColor(Color.BLUE);
g.fillRect(25, y, breidd, lengd);
System.out.println("Y er "+y);
}
public void setyHradi(int hradi)
{
yHradi = hradi;
}
}

According to this Thread ("http://forums.netbeans.org/post-134877.html") the problem is that you pass a reference of this to an outside class while not fully initialized (in constructor). So you need to do this later in an initialization method

Related

Make a rectangle move up and down on key press in jframe

hi im trying to make a rectangle move up and down on key press in jframe.
but the rectangle only goes down when i press the up or down arrow key and it does not stop. and i cant see where i have made a mistake.
i don't think the mistake is in file one but as said, i cant find it so it maybe is.
file 1
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class test{
public static void main (String[] arg) {
JFrame window = new JFrame();
test2 t2 = new test2();
window.add(t2);
window.setSize(1000,1000);
window.setTitle("TEST");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}
file 2
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class test2 extends JPanel implements ActionListener, KeyListener{
Timer t = new Timer(5, this);
double x = 0, y = 0, velx = 0, vely = 0;
public test2() {
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Rectangle((int)x, (int)y, 20, 40));
}
public void actionPerformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}
public void up() {
vely = -1.5;
velx = 0;
}
public void down() {
vely = 1.5;
velx = 0;
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP); {
up();
}
if (code == KeyEvent.VK_DOWN); {
down();
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
}
Your logic is not very optimal. You should have your code more like this:
/** DELETE THIS METHOD!
public void actionPerformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}**/
private static final double MOVEMENT = 1.5;
public void up() {
x += -MOVEMENT; // Mind the - in front of MOVEMENT to negate the value.
// No need to change y if it does not change at all
repaint() // Repaint _after_ you changed the coordinates
}
public void down() {
x += MOVEMENT; // Mind that there is no - infront of this MOVEMENT.
// No need to change y if it does not change at all
repaint() // Repaint _after_ you changed the coordinates
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP); {
up();
}
if (code == KeyEvent.VK_DOWN); {
down();
}
}
You miss calling repaint() onYour JPanel after changing the position of x,y;
Also note that your events will only trigger twice (OnKeyDown and OnKeyUp).

The player score increments by 9 instead of 1

So in this game i'm testing out, whenever the ball hits the paddle, I want the score to increase by 1. But instead it increases by 9 instead. How can I fix this? Here is the code. The 2nd method which is the update() method contains the score increase.
public class PlayState extends State {
private Catcher catcher;
private Ball ball;
boolean visible ;
private int playerScore = 0;
private Font scoreFont;
#Override
public void init() {
catcher = new Catcher(400,425,80,25);
ball= new Ball(200,0,40,40);
}
#Override
public void update() {
visible=true;
catcher.update();
ball.update();
if(ballCollides(catcher)){
playerScore++;
visible = false;
}
}
#Override
public void render(Graphics g) {
//Draw Background
g.setColor(Color.blue);
g.fillRect(0, 0, GameMain.GAME_WIDTH, GameMain.GAME_HEIGHT);
//Draw Ball(s)
if(visible == true){
g.setColor(Color.green);
g.fillOval(ball.getX(),ball.getY(),ball.getWidth(),ball.getHeight());
}
// Draw catcher
g.setColor(Color.white);
g.fillRect(catcher.getX(), catcher.getY(), catcher.getWidth(),
catcher.getHeight());
// Draw Score
g.setFont(scoreFont); // Sets scoreFont as current font
g.setColor(Color.white);
g.drawString("" + playerScore, 350, 40); // Draws String using current font
}
#Override
public void onClick(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void onKeyPress(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_RIGHT){
catcher.moveRight();
}
if (e.getKeyCode()==KeyEvent.VK_LEFT){
catcher.moveLeft();
}
}
private boolean ballCollides(Catcher c) {
return ball.getRect().intersects(c.getRect());
}
#Override
public void onKeyRelease(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_LEFT
|| e.getKeyCode() == KeyEvent.VK_RIGHT) {
catcher.stop();
}
}
}
2nd blck of code where the update method is being called
package com.jamescho.game.main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;
import com.jamescho.framework.util.InputHandler;
import com.jamescho.game.state.LoadState;
import com.jamescho.game.state.State;
#SuppressWarnings("serial")
public class Game extends JPanel implements Runnable {
private int gameWidth;
private int gameHeight;
private Image gameImage;
private Thread gameThread;
private volatile boolean running;
private volatile State currentState;
private InputHandler inputHandler;
public Game(int gameWidth, int gameHeight) {
this.gameWidth = gameWidth;
this.gameHeight = gameHeight;
setPreferredSize(new Dimension(gameWidth, gameHeight));
setBackground(Color.BLACK);
setFocusable(true);
requestFocus();
}
public void setCurrentState(State newState) {
System.gc();
newState.init();
currentState = newState;
inputHandler.setCurrentState(currentState);
}
#Override
public void addNotify() {
super.addNotify();
initInput();
setCurrentState(new LoadState());
initGame();
}
private void initGame() {
running = true;
gameThread = new Thread(this, "Game Thread");
gameThread.start();
}
#Override
public void run() {
// These variables should sum up to 17 on every iteration
long updateDurationMillis = 0; // Measures both update AND render
long sleepDurationMillis = 0; // Measures sleep
while (running) {
long beforeUpdateRender = System.nanoTime();
long deltaMillis = updateDurationMillis + sleepDurationMillis;
updateAndRender(deltaMillis);
updateDurationMillis = (System.nanoTime() - beforeUpdateRender) / 1000000L;
sleepDurationMillis = Math.max(2, 17 - updateDurationMillis);
try {
Thread.sleep(sleepDurationMillis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// End game immediately when running becomes false.
System.exit(0);
}
private void updateAndRender(long deltaMillis) {
currentState.update(deltaMillis / 1000f);
prepareGameImage();
currentState.render(gameImage.getGraphics());
renderGameImage(getGraphics());
}
private void prepareGameImage() {
if (gameImage == null) {
gameImage = createImage(gameWidth, gameHeight);
}
Graphics g = gameImage.getGraphics();
g.clearRect(0, 0, gameWidth, gameHeight);
}
public void exit() {
running = false;
}
private void renderGameImage(Graphics g) {
if (gameImage != null) {
g.drawImage(gameImage, 0, 0, null);
}
g.dispose();
}
private void initInput() {
inputHandler = new InputHandler();
addKeyListener(inputHandler);
addMouseListener(inputHandler);
}
}
It appears as if ballCollides may return true across multiple updates for a single collision. I am not sure of this without looking at the code for the entire program, but based on what has been posted this would seem to be the most likely case.
One fix would be to keep track of the previous collision state for each catcher and ball combination (if there can be more than a single ball and catcher), and only update the score when the current state is colliding and the previous state was non-colliding.
E.g.
// Example using a single previousCollides state variable...
// Not suitable for a multi catcher / multi-ball game.
// The modifications break the contract this methods name seems to
// imply so the previousCollides logic should probably exist elsewhere
// and this code is only to illustrate the idea.
private boolean ballCollides(Catcher c) {
boolean collides = ball.getRect().intersects(c.getRect());
boolean result = collides && !previousCollides;
previousCollides = collides;
return result;
}
The above is just an example, where to actually keep track of the previous collision data is up to you. Maybe it should be kept within the catcher object itself as that would seem to make the most sense.

how to draw multiple rectangles

so I am trying to make a simple program where you click on the screen and it creates a block that falls and collides with a larger block beneath and sticks to it. Kind of like a simple collision program. The problem is when I create one block it deletes the block previously. I made an array, but it still does this. Do any of you know what Im doing wrong? Im sure its a simple fix.
public class Screen extends JPanel implements Runnable {
public static JLabel statusbar; //displays a status bar showing what mouse movements are taking place
private Image cat; //image of the cat
public int xCoord ; //get the coordinates of the mouse pressed
public int yCoord ;
public int xCreate;
public int yCreate;
public Rectangle Ground;
public Rectangle Block;
public boolean isClicked = false;
public int clickCount = 0;
Rectangle blocks[] = new Rectangle[10];
int blocknum = 0;
public Screen(Frame frame) {
loadPic(); //calls the loadPic method above
Handlerclass handler = new Handlerclass(); //creates a new class to use the mouse motion listener
System.out.println("mouse works!");
addMouseListener(handler);
addMouseMotionListener(handler);
statusbar = new JLabel("default");
add(statusbar);
}
public void run(){ //this is the game run loop
System.out.println("this is running");
try{
} catch(Exception e) {} //exception handling
}
public void loadPic(){ //loads the picture from the other project but its the same pic
cat = new ImageIcon("C:\\Users\\Camtronius\\Documents\\NetBeansProjects\\Moving Block Proj\\src\\MovingBlock\\catIcon1.png").getImage(); //gets the image
System.out.println("Image Loaded!");
}
#Override public void paintComponent(Graphics g){
super.paintComponent(g); //paints the component, the picture, on top
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(cat, xCoord, yCoord, null);
g2d.setColor(Color.BLUE);
Ground = new Rectangle(0,450,550,50);
g2d.fillRect(0,450, 550, 50);
for(Rectangle blocknum : blocks){
if (blocks != null) {
g2d.setColor(Color.RED);
g2d.fillRect(xCreate,yCreate,50,50);
System.out.println(blocknum);
}
}
//move();
}
public void move(){
if(yCreate<400){
yCreate+=1;
}else{
}
if(Ground.intersects(blocks[blocknum])){
yCreate=400;
System.out.println("contains!");
}
}
private class Handlerclass implements MouseListener, MouseMotionListener{
public void mouseClicked(MouseEvent event){
}
public void mousePressed(MouseEvent event){
}
public void mouseReleased(MouseEvent event){
if(blocknum<blocks.length){
xCreate=event.getX();
yCreate=event.getY();
blocks[blocknum] = new Rectangle(50,50, xCreate, yCreate);
repaint();
}
blocknum=blocknum+1;
}
public void mouseEntered(MouseEvent event){
}
public void mouseExited(MouseEvent event){
}
public void mouseDragged(MouseEvent event){
}
public void mouseMoved(MouseEvent event){
statusbar.setText(String.format("Coordinates are: %d, %d", event.getX(),event.getY()));
xCoord=event.getX();
yCoord=event.getY();
}
}
}
Painting is a destructive process. That is, when a new paint cycle runs, the previous contents of the Graphics context should be cleared...
So, in you paintComponent method you are only painting the last block...
if(isClicked = true){
blocks[blocknum] = new Rectangle(50,50, xCreate, yCreate);
g2d.setColor(Color.RED);
g2d.fillRect(xCreate,yCreate,50,50);
System.out.println(blocknum);
repaint(); // THIS IS A BAD IDEA
}
DO NOT call any method that might cause repaint to be called. This will put you in a potential cycle of death that will consume your CPU.
Instead, you should loop through the blocks array and paint each one...
for (Rectangle block : blocks) {
if (block != null) {
g2d.setColor(Color.RED);
g2d.fill(block);
}
}
And in you mouseReleased method, you should be adding the new rectangles...
public void mouseReleased(MouseEvent event){
blocknum=blocknum+1;
if (blocknum < blocks.length) {
xCreate=event.getX();
yCreate=event.getY();
blocks[blocknum] = new Rectangle(xCreate, yCreate, 50, 50);
}
}
I'd suggest you take a look at Custom Painting, Painting in AWT and Swing and Concurrency in Swing for more details

How to create random monsters

I am making a game like Space Impact. In my game the rockets are working correctly, but I can't create monsters randomly. Monsters are on the screen but they aren't moving so they aren't active
How can I do this?
public class Dnm extends JFrame implements Runnable {
Graphics dbg;
Image dbImage;
Image Pik1;
Image Boss;
static ImageIcon active;
int x, y, xDirection, yDirection, BossX, BossY;
public void run() {
try {
while (true) {
move();
boss();
Thread.sleep(10);
}
} catch (Exception e) {
System.out.println("Uh-oh, something went wrong!.");
}
}
private void move() {
x += xDirection;
y += yDirection;
}
private void boss() {
while (BossX == 0) {
BossX = getX() - 1;
}
Random rastgele = new Random(getY());
BossY = rastgele.nextInt();
}
public void setXDirection(int xdir) {
xDirection = xdir;
}
public void setYDirection(int ydir) {
yDirection = ydir;
}
// KEY COMMANDS //
public class AL extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
setXDirection(-1);
}
if (keyCode == e.VK_RIGHT) {
setXDirection(+1);
}
if (keyCode == e.VK_UP) {
setYDirection(-1);
}
if (keyCode == e.VK_DOWN) {
setYDirection(+1);
}
}
#Override
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
setXDirection(0);
}
if (keyCode == e.VK_RIGHT) {
setXDirection(0);
}
if (keyCode == e.VK_UP) {
setYDirection(0);
}
if (keyCode == e.VK_DOWN) {
setYDirection(0);
}
}
#Override
public void keyTyped(KeyEvent e) {
}
}
// CONSTRUCTOR //
public Dnm() {
//Image Import
ImageIcon still = new ImageIcon("img/rocket.png");
Pik1 = still.getImage();
addKeyListener(new AL());
setTitle("Dnm");
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(true);
setVisible(true);
x = 15;
y = 15;
}
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paintComponent(Graphics g) {
ImageIcon background = new ImageIcon("img/space.jpeg");
Image background1 = background.getImage();
ImageIcon still1 = new ImageIcon("img/Alien.png");
Boss = still1.getImage();
g.setColor(Color.red);
g.drawImage(background1, 0, 0, this);
g.drawImage(Boss, BossX, BossY, this);
g.drawImage(Pik1, x, y, this);
g.setColor(Color.blue);
repaint();
}
public static void main(String[] args) {
Dnm game = new Dnm();
Thread t1 = new Thread(game);
t1.start();
}
}
Thank You.
With your code being incomplete, it is hard to say for sure, but this line looks suspicious:
while (BossX == 0) {
BossX = getX() - 1;
}
This code is mostly likely going to be executed once, right? If BossX is initially zero, the code executes where you change its value. On the next update, BossX is not zero (presumably), so the code doesn't execute. Since BossX is the X coordinate where you are drawing the boss, then it will not move. Instead it just gets redrawn over and over in the same spot.
To get the monster to move randomly, increment or decrement both the X and Y coordinate values randomly during each game loop. Add a second random variable to cause them to move at random speeds in the random direction (by adjusting the coordinate value by a value greater than one).
As NPE commented, you should step through the code in a debugger and find out precisely what is going on.
I am fairly a beginner at programming, but here is my best attempt:
I would create a method that is called every x seconds that generates a random number using Math.Random(). I would say
int number = .5;
if(number > Math.Random())
GenerateMonster();
Your GenerateMonster method would then create a new object with the default values for monster. In order for the monster's created to act a certain way, you need to inherit those functions wherever you defined how you want the monster to act. I don't see the code for these functions so I am assuming you just didn't list them. Hope this at least helps. Good Luck!

Java Graphics how to draw image in keyPressed

I am learning something new and somewhat difficult in Java-which is graphics! Below I explain what the two classes do. My new obstacle right now is coming up with a way to draw a different image for (ie: a projectile like a laser) coming from the ball by only pressing Z.
The problem is if I write a method for example: "g.drawImage(laser,laser_dx,laser_dy,this) in the if statement that contains "KeyEvent.VK_Z", my keyPressed method all of sudden says "this method is not used locally". What are my approaches to solving such an obstacle?
What I've done so far is written a nested class inside the "GameBoard" class that contains all the keyboard events of my program.
private class Adapter extends KeyAdapter
{
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_RIGHT)
{
ball_dx += ball_velocity;
}
if(keyCode == KeyEvent.VK_LEFT)
{
ball_dx -= ball_velocity;
}
if(keyCode == KeyEvent.VK_Z){
}
}
}
Here's the drawing graphics method in a separate class called "Gameboard": This class just draws the image of a green ball(which is a .png image) and it can move left and right with the arrow keys!
public class GameBoard extends JPanel implements ActionListener
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(ball, ball_dx, ball_dy, this);
Toolkit.getDefaultToolkit().sync();
}
public void actionPerformed(ActionEvent arg0)
{
repaint();
}
}
You have to rethink the logic: the code that handles the key events and the code that draws everything should share a state so that
events set the state
drawings change according to the state
Just to make it simple and to give you the idea:
boolean isLaser = false;
public void keyPressed(KeyEvent e) {
isLaser = true;
}
public void keyReleased(KeyEvent e) {
isLaser = false;
}
public void paintComponent(Graphics g) {
if (isLaser)
// do something
}
Of course in a more complex environment you would have a more structured solution like
List<Entity> entities = new ArrayList<Entity>();
public void paintComponent(Graphics g) {
for (Entity e : entities)
e.draw(g);
}
public void keyPressed() {
entities.add(new LaserEntity(...));
}

Categories

Resources