I have KeyEvents for a sprite for moving left, right, up and down. I was just messing around and was thinking ahead for another project in which I want the sprite to jump. It doesn't have to be fully realistic as I am just beginning. What I have is when the space bar is pressed, it will cause the sprite to jump, lets say "dy = -3". So then I have the KeyEvent for keyReleased, it will fall, "dy = -2". This does not work as the sprite just continues to fall...can someone shine some light?
Entire code:
package collision;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.ImageIcon;
public class Craft {
private String craft = "pelican.png";
private int dx;
private int dy;
private int x;
private int y;
private int width;
private int height;
private boolean visible;
private Image image;
private ArrayList missiles;
public Craft() {
ImageIcon ii = new ImageIcon(this.getClass().getResource(craft));
image = ii.getImage();
width = image.getWidth(null);
height = image.getHeight(null);
missiles = new ArrayList();
visible = true;
x = 100;
y = 300;
}
public void move() {
x += dx;
y += dy;
if (x < 1) {
x = 1;
}
if (y < 1) {
y = 1;
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Image getImage() {
return image;
}
public ArrayList getMissiles() {
return missiles;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public boolean isVisible() {
return visible;
}
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
}
if (key == KeyEvent.VK_V){
dx = 6;
}
if (key == KeyEvent.VK_LEFT) {
dx = -1;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 2;
}
if (key == KeyEvent.VK_UP) {
dy = -1;
}
if (key == KeyEvent.VK_DOWN) {
dy = 1;
}
}
public void fire() {
missiles.add(new Missile(x + width, y + height/2));
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
if (key == KeyEvent.VK_SPACE) {
}
if (key == KeyEvent.VK_RIGHT) {
dx = 0;
}
if (key == KeyEvent.VK_UP) {
dy = 0;
}
if (key == KeyEvent.VK_DOWN) {
dy = 0;
}
}
}
As you may have noticed Im new to Java as well as game programming. All I want is the sprite to go up, then come back down. It will always remain stationary if that helps. The sprite just keeps jumping until he is hit by an on coming obstacle. I know there is code for other movements, but those will be removed once I start on next sprite.
This is basic concept. Your implementation will change depending on the implementation of your engine.
The basic idea is the player has a vertical delta which is changed over time by gravity. This effects the sprites vertical speed.
This implementation also has a re-bound delta, which allows the sprite to re-bound rather the "stopping" suddenly. The re-bound is effected by a re-bound degradation, which reduces the amount of re-bound on each re-bound.
This simulates a game character, so you'll need to hit Space to start it bouncing...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class JumpingSprite {
public static void main(String[] args) {
new JumpingSprite();
}
public JumpingSprite() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
protected static final int SPRITE_HEIGHT = 10;
protected static final int SPRITE_WIDTH = 10;
private float vDelta; // The vertical detla...
private float rbDelta; // Rebound delta...
private float rbDegDelta; // The amount the rebound is degradation...
private int yPos; // The vertical position...
private float gDelta; // Gravity, how much the vDelta will be reduced by over time...
private Timer engine;
private boolean bounce = false;
public TestPane() {
yPos = getPreferredSize().height - SPRITE_HEIGHT;
vDelta = 0;
gDelta = 0.25f;
// This is how much the re-bound will degrade on each cycle...
rbDegDelta = 2.5f;
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "jump");
am.put("jump", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// Can only bound when we're actually on the ground...
// You might want to add fudge factor here so that the
// sprite can be within a given number of pixels in order to
// jump again...
if (yPos + SPRITE_HEIGHT == getHeight()) {
vDelta = -8;
rbDelta = vDelta;
bounce = true;
}
}
});
engine = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int height = getHeight();
// No point if we've not been sized...
if (height > 0) {
// Are we bouncing...
if (bounce) {
// Add the vDelta to the yPos
// vDelta may be postive or negative, allowing
// for both up and down movement...
yPos += vDelta;
// Add the gravity to the vDelta, this will slow down
// the upward movement and speed up the downward movement...
// You may wish to place a max speed to this
vDelta += gDelta;
// If the sprite is not on the ground...
if (yPos + SPRITE_HEIGHT >= height) {
// Seat the sprite on the ground
yPos = height - SPRITE_HEIGHT;
// If the re-bound delta is 0 or more then we've stopped
// bouncing...
if (rbDelta >= 0) {
// Stop bouncing...
bounce = false;
} else {
// Add the re-bound degregation delta to the re-bound delta
rbDelta += rbDegDelta;
// Set the vDelta...
vDelta = rbDelta;
}
}
}
}
repaint();
}
});
engine.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth() - 1;
int xPos = (width - SPRITE_WIDTH) / 2;
g2d.drawOval(xPos, yPos, SPRITE_WIDTH, SPRITE_HEIGHT);
g2d.dispose();
}
}
}
Well I can think of one way. It involves some complex amounts of math (parabola). So i'm going to provide a very simple answer.
int y = 0;
and in the method that tests for the spacebar...
if (y !< 1){
if (y < 30){
y += 1;
}
if (y > 30){
y -= 1;
}
}
I haven't tested it out yet, but it should work in theory....But it won't animate anything, this code is only going to take the sprites Y value and make it go up. That's just about the easiest jumping method that can exist....
Related
I have been trying my best to work out collision detection between Pacman and the walls, however my implementation doesn't seem to work as correctly
Does collision detection work at all? Yes
Does it behave correctly? No
How is it currently behaving? When you hit a wall it stops Pacman
from moving which is okay, however any new key presses to move only changes
the images axis (up, right, down or left depending on key press),
it will not move the Pacman beyond its current location after hitting the wall.
Any assistance would be greatly appreciated. thanks in advance
GamePanel.java
package pacman;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
private Thread animator;
private boolean isRunning;
private Map map = new Map();
public GamePanel(){
this.setBackground(Color.BLACK);
this.setDoubleBuffered(true);
addKeyListener(new TAdapter());
setFocusable(true);
}
#Override
public void run() {
isRunning = true;
System.out.println("Is running? "+isRunning);
long startTime, timeDiff, sleepTime;
startTime = System.currentTimeMillis();
while(isRunning){
repaint();
gameUpdate();
timeDiff = System.currentTimeMillis() - startTime;
sleepTime = 5 - timeDiff;
try{
Thread.sleep(sleepTime);
}
catch(InterruptedException ex){
System.exit(0);
}
startTime = System.currentTimeMillis();
}
// gameOver(); not implemented yet, will focus on this when I have some basic animation and the game loop working to satisfaction.
}
#Override
public void addNotify(){
super.addNotify();
startGame();
}
public void startGame(){
if(animator == null || !isRunning){
animator = new Thread(this);
animator.start();
}
} //end of StartGame method
public void gameUpdate(){
map.getPlayer().move();
checkCollision();
} //implementation of ingame updates such as pacman getting killed.
public void checkCollision(){ //this is where I officially set collision up
for(int i = 0; i < map.tiles.length; i++){
for(int j = 0; j < map.tiles.length; j++){
if(map.tiles[i][j] != null){
if(map.getPlayer().getPlayerBox().intersects(map.tiles[i][j].getR())){
map.getPlayer().setColliding(true);
System.out.println("OWW"+map.tiles[i][j].getR().getLocation());
}
}
}
}
}
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D) g;
super.paintComponent(g);
if(isRunning){
drawDot(g2d);
drawPlayer(g2d);
map.drawMap(g2d);
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void drawDot(Graphics2D g){
g.setColor(Color.GREEN);
for(int x= 0; x < 400; x++){
for(int y = 0; y < 400; y++){
g.drawRect(x * 20, y * 20, 1, 1);
}
}
}
public void drawPlayer(Graphics2D g){
g.drawImage(map.getPlayer().getImage(), map.getPlayer().getX(),map.getPlayer().getY(), this);
}
private class TAdapter extends KeyAdapter{
#Override
public void keyPressed(KeyEvent e) {
map.getPlayer().keyPressed(e);
}
#Override
public void keyReleased(KeyEvent e) {
map.getPlayer().keyReleased(e);
}
}
}
Player.java
package pacman;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
public class Player extends Commons{
private int dx, dy;
private int speed = 1;
private static int playerWidth = 52; //these figures seem off, but that is because the image is not designed correctly or the pacman image is not obeying the logic of not going passed the frame size.
private static int playerHeight = 82;
private Rectangle playerBox;
private Image playerImg = new ImageIcon(Player.class.getResource("Pacman.png")).getImage();
private Image playerImgUp = new ImageIcon(Player.class.getResource("PacmanUp.png")).getImage();
private Image playerImgLeft = new ImageIcon(Player.class.getResource("PacmanLeft.png")).getImage();
private Image playerImgDown = new ImageIcon(Player.class.getResource("PacmanDown.png")).getImage();
private boolean isColliding = false;
public Player(){
this.setX(320);
this.setY(280);
playerBox = new Rectangle(this.getX(), this.getY(),40,40);
}
public void setSpeed(int sp){
speed = sp;
}
public Image getImage(){
if(dy == 1){
return playerImgDown;
}
else if(dy == -1){
return playerImgUp;
}
else if(dx == -1){
return playerImgLeft;
}
else
return playerImg;
}//Responsible for displaying pacman image based on direction of pacman's movement.
void move(){
int x = this.getX();
int y = this.getY();
/*
* This is the part where I am trying to implement some degree of logic to stop it from moving
*/
if(isColliding == false){
this.setX(x += dx);
playerBox.setLocation(x, y);
this.setY(y += dy);
}else if(isColliding == true){
this.setColliding(false);
this.setX(this.getX());
this.setY(this.getY());
}
if (this.getX() <= 1) {
this.setX(1);
}
if (this.getX() >= 400 - playerWidth) {
this.setX(400 - playerWidth);
}
if (this.getY() <= 2) {
this.setY(2);
}
if (this.getY() >= 400 - playerHeight ) {
this.setY(400 - playerHeight);
}
}//Most simplist form of collision detection, stops pacman from leaving the JFrame
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT ){
dx = -speed;
dy = 0;
}
if(key == KeyEvent.VK_RIGHT){
dx = speed;
dy = 0;
}
if(key == KeyEvent.VK_UP){
dx = 0;
dy = -speed;
}
if(key == KeyEvent.VK_DOWN){
dx = 0;
dy = speed;
}
if(key == KeyEvent.VK_ESCAPE){
System.exit(0);
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
dy = 0;
}
if(key == KeyEvent.VK_RIGHT){
dy = 0;
}
if(key == KeyEvent.VK_UP){
dx = 0;
}
if(key == KeyEvent.VK_DOWN){
dx = 0;
}
}//end of key release
public Rectangle getPlayerBox() {
return playerBox;
}
public void setPlayerBox(Rectangle playerBox) {
this.playerBox = playerBox;
}
public boolean isColliding() {
return isColliding;
}
public void setColliding(boolean isColliding) {
this.isColliding = isColliding;
}
}// end of class
It looks like what happens is the player enters a tile which causes collision and isColliding is set to true.
The next iteration of the game update calls movement code which checks the player's isColliding boolean. That condition is true and no movement occurs. Next, collision is checked and we haven't moved out of the tile causing the collision so we are stuck in this tile.
I suggest when collision happens to move the player just out of the colliding tile.
We know which direction the player is moving so we can use the inverse direction (multiply dx and dy by -1) to move the player out of the colliding tile.
Look I'm going to be up front about this. My assignment is due soon and i've spent way too many hours trying to fix this problem with no success at all. I'm essentially clueless at what the issue is and I really dont know where to look. I have 5 classes, I will try and post them all to ensure I get the answer, I am unable to change GameManager or Goal but I am allowed to change any other class.
The problem lines are this.canvasGraphics.drawImage(player.getCurrentImage() where drawImage says it isnt applicable for the arguments
and
this.enemies[i].getX() - (this.enemies[i].getCurrentImage().getWidth() / 2),
this.enemies[i].getY() - (this.enemies[i].getCurrentImage().getHeight() / 2), null);
where getWidth and getHeight show an almost identical error
thanks in advance
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.awt.Font;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class GameManager extends JFrame implements KeyListener {
private int canvasWidth;
private int canvasHeight;
private int borderLeft;
private int borderTop;
private BufferedImage canvas;
private Stage stage;
private Enemy[] enemies;
private Player player;
private Goal goal;
private Graphics gameGraphics;
private Graphics canvasGraphics;
private int numEnemies;
private boolean continueGame;
public static void main(String[] args) {
// During development, you can adjust the values provided in the brackets below
// as needed. However, your code must work with different/valid combinations
// of values.
int choice;
do{
GameManager managerObj = new GameManager(1920, 1080);
choice=JOptionPane.showConfirmDialog(null,"Play again?", "", JOptionPane.OK_CANCEL_OPTION);
}while(choice==JOptionPane.OK_OPTION);
System.exit(0);
}
public GameManager(int preferredWidth, int preferredHeight) {
int maxEnemies;
try{
maxEnemies=Integer.parseInt(JOptionPane.showInputDialog("How many enemies? (Default is 5)"));
if (maxEnemies<0)
maxEnemies=5;
}
catch (Exception e){
maxEnemies=5;
}
this.borderLeft = getInsets().left;
this.borderTop = getInsets().top;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if (screenSize.width < preferredWidth)
this.canvasWidth = screenSize.width - getInsets().left - getInsets().right;
else
this.canvasWidth = preferredWidth - getInsets().left - getInsets().right;
if (screenSize.height < preferredHeight)
this.canvasHeight = screenSize.height - getInsets().top - getInsets().bottom;
else
this.canvasHeight = preferredHeight - getInsets().top - getInsets().bottom;
setSize(this.canvasWidth, this.canvasHeight);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
addKeyListener(this);
Random rng = new Random();
this.canvas = new BufferedImage(this.canvasWidth, this.canvasHeight, BufferedImage.TYPE_INT_RGB);
// Create a Stage object to hold the background images
this.stage = new Stage();
// Create a Goal object with its initial x and y coordinates
this.goal = new Goal((Math.abs(rng.nextInt()) % (this.canvasWidth)),
(Math.abs(rng.nextInt()) % this.canvasHeight));
// Create a Player object with its initial x and y coordinates
this.player = new Player((Math.abs(rng.nextInt()) % (this.canvasWidth)),
(Math.abs(rng.nextInt()) % this.canvasHeight));
// Create the Enemy objects, each with a reference to this (GameManager) object
// and their initial x and y coordinates.
this.numEnemies = maxEnemies;
this.enemies = new Enemy[this.numEnemies];
for (int i = 0; i < this.numEnemies; i++) {
this.enemies[i] = new Enemy(this, Math.abs(rng.nextInt()) % (this.canvasWidth),
Math.abs(rng.nextInt()) % this.canvasHeight);
}
this.gameGraphics = getGraphics();
this.canvasGraphics = this.canvas.getGraphics();
this.continueGame = true;
long gameStartTime=System.nanoTime();
while (this.continueGame) {
updateCanvas();
}
this.stage.setGameOverBackground();
double gameTime=(System.nanoTime()-gameStartTime)/1000000000.0;
updateCanvas();
this.gameGraphics.setFont(new Font(this.gameGraphics.getFont().getFontName(), Font.PLAIN, 50));
if (gameTime<1)
this.gameGraphics.drawString("Oops! Better luck next time...", this.canvasWidth/3, this.canvasHeight/2 - 50);
else
this.gameGraphics.drawString("You survived " + String.format("%.1f", gameTime)+ " seconds with "+this.numEnemies+" enemies!",
this.canvasWidth/4, this.canvasHeight/2 - 50);
return;
}
public void updateCanvas() {
long start = System.nanoTime();
this.goal.performAction();
// If the player is alive, this should move the player in the direction of the
// key that has been pressed
// Note: See keyPressed and keyReleased methods in the GameManager class.
this.player.performAction();
// If the enemy is alive, the enemy must move towards the Player. The Player object
// is obtained via the GameManager object that is given at the time of creating an Enemy
// object.
// Note: The amount that the enemy moves by must be much smaller than that of
// the player above or else the game becomes too hard to play.
for (int i = 0; i < this.numEnemies; i++) {
this.enemies[i].performAction();
}
if ((Math.abs(this.goal.getX() - this.player.getX()) < (this.goal.getCurrentImage().getWidth() / 2))
&& (Math.abs(this.goal.getY() - this.player.getY()) < (this.goal.getCurrentImage().getWidth() / 2))) {
for (int i = 0; i < this.numEnemies; i++) {
// Sets the image of the enemy to the "dead" image and sets its status to
// indicate dead
this.enemies[i].die();
}
// Sets the background of the stage to the finished game background.
this.stage.setGameOverBackground();
this.continueGame = false;
}
// If an enemy is close to the player or the goal, the player and goal die
int j = 0;
while (j < this.numEnemies) {
if ((Math.abs(this.player.getX() - this.enemies[j].getX()) < (this.player.getCurrentImage().getWidth() / 2))
&& (Math.abs(this.player.getY() - this.enemies[j].getY()) < (this.player.getCurrentImage().getWidth()
/ 2))) {
this.player.die();
this.goal.die();
this.stage.setGameOverBackground();
j = this.numEnemies;
this.continueGame = false;
}
else if ((Math.abs(this.goal.getX() - this.enemies[j].getX()) < (this.goal.getCurrentImage().getWidth() / 2))
&& (Math.abs(this.goal.getY() - this.enemies[j].getY()) < (this.goal.getCurrentImage().getWidth()
/ 2))) {
this.player.die();
this.goal.die();
this.stage.setGameOverBackground();
j = this.numEnemies;
this.continueGame = false;
}
j++;
}
try {
// Draw stage
this.canvasGraphics.drawImage(stage.getCurrentImage(), 0, 0, null);
// Draw goal
this.canvasGraphics.drawImage(this.goal.getCurrentImage(),
this.goal.getX() - (this.goal.getCurrentImage().getWidth() / 2),
this.goal.getY() - (this.goal.getCurrentImage().getHeight() / 2), null);
// Draw player
this.canvasGraphics.drawImage(player.getCurrentImage(),
this.player.getX() - (this.player.getCurrentImage().getWidth() / 2),
this.player.getY() - (this.player.getCurrentImage().getHeight() / 2), null);
// Draw enemies
for (int i = 0; i < this.numEnemies; i++) {
this.canvasGraphics.drawImage(this.enemies[i].getCurrentImage(),
this.enemies[i].getX() - (this.enemies[i].getCurrentImage().getWidth() / 2),
this.enemies[i].getY() - (this.enemies[i].getCurrentImage().getHeight() / 2), null);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
// Draw everything.
this.gameGraphics.drawImage(this.canvas, this.borderLeft, this.borderTop, this);
long end = System.nanoTime();
this.gameGraphics.setFont(new Font(this.gameGraphics.getFont().getFontName(), Font.PLAIN, 15));
this.gameGraphics.drawString("FPS: " + String.format("%2d", (int) (1000000000.0 / (end - start))),
this.borderLeft + 50, this.borderTop + 75);
return;
}
public Player getPlayer() {
return this.player;
}
public void keyPressed(KeyEvent ke) {
// Below, the setKey method is used to tell the Player object which key is
// currently pressed.
// The Player object must keep track of the pressed key and use it for
// determining the direction
// to move.
// Important: The setKey method in Player must not move the Player.
if (ke.getKeyCode() == KeyEvent.VK_LEFT)
this.player.setKey('L', true);
if (ke.getKeyCode() == KeyEvent.VK_RIGHT)
this.player.setKey('R', true);
if (ke.getKeyCode() == KeyEvent.VK_UP)
this.player.setKey('U', true);
if (ke.getKeyCode() == KeyEvent.VK_DOWN)
this.player.setKey('D', true);
if (ke.getKeyCode() == KeyEvent.VK_ESCAPE)
this.continueGame = false;
return;
}
#Override
public void keyReleased(KeyEvent ke) {
// Below, the setKey method is used to tell the Player object which key is
// currently released.
// The Player object must keep track of the pressed key and use it for
// determining the direction
// to move.
// Important: The setKey method in Player must not move the Player.
if (ke.getKeyCode() == KeyEvent.VK_LEFT)
this.player.setKey('L', false);
if (ke.getKeyCode() == KeyEvent.VK_RIGHT)
this.player.setKey('R', false);
if (ke.getKeyCode() == KeyEvent.VK_UP)
this.player.setKey('U', false);
if (ke.getKeyCode() == KeyEvent.VK_DOWN)
this.player.setKey('D', false);
return;
}
#Override
public void keyTyped(KeyEvent ke) {
return;
}
}
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.util.*;
public class Goal {
private int x;
private int y;
private BufferedImage imageCurrent;
private BufferedImage imageRunning;
private BufferedImage imageOver;
private int stepSize;
private Random rng; // Tip: Code that students write must not use randomness
public Goal(int x, int y) {
try {
this.imageRunning = ImageIO.read(new File("goal-alive.png"));
this.imageOver = ImageIO.read(new File("goal-dead.png"));
} catch (IOException e) {
e.printStackTrace();
}
this.x = x;
this.y = y;
this.stepSize = 10;
this.rng = new Random(x + y); // Tip: Code that students write (elsewhere) must not use any randomness.
this.imageCurrent = this.imageRunning;
return;
}
public void performAction() {
// The code below shows how the Goal can be moved by manipulating its x and y
// coordinates.
// Tip: Code that students write (elsewhere) must not use any randomness.
this.x += this.rng.nextInt() % stepSize;
this.y += this.rng.nextInt() % stepSize;
return;
}
public int getY() {
return this.y;
}
public int getX() {
return this.x;
}
public BufferedImage getCurrentImage() {
return this.imageCurrent;
}
public void die() {
this.imageCurrent = this.imageOver;
return;
}
}
import java.awt.Image;
public class Enemy {
private Image CurrentImage;
private int x;
private int y;
public Enemy(GameManager gameManager, int x, int y) {
}
public void performAction() {
}
public void die() {
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public Image getCurrentImage() {
return CurrentImage;
}
}
import java.awt.Dimension;
public class Player {
private Dimension CurrentImage;
private int x;
private int y;
public Player(int x1, int y1) {
}
public void performAction() {
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public Dimension getCurrentImage() {
return CurrentImage;
}
public void die() {
}
public void setKey(char c, boolean b) {
}
}
import java.awt.Image;
public class Stage {
public void setGameOverBackground() {
}
public Image getCurrentImage() {
return null;
}
}
Player.getCurrentImage() returns a Dimension, not an Image.
i'm teaching myself to program in java, and i have decided to make an space invader game. i got my ship moving in any direction, but i have a problem with my bullet being fired. now i know that my y-coordinate of the bullet are being updated every time my ship moves, but it is not firing. I need someone to help me get it to fire if possible. any help is welcome.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
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 Panel extends JPanel implements KeyListener, ActionListener{
private int x;
private int y;
private int dx;
private int dy;
int bx;
int by;
Rectangle bullet;
Timer timer;
private Image image;
public Panel() {
timer = new Timer(30, this);
setBackground(Color.black);
addKeyListener(this);
setFocusable(true);
timer.start();
x=130;
y=430;
bx=xPost()+55;
by=yPost();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
ImageIcon ii= new ImageIcon("C:\\Users\\TriZam\\workspace\\LearningSprite\\ship.png");
image=ii.getImage();
g.drawImage(image, x, y, this);
doDrawing(g);
}
public void move(){
// thhis method will be placed inside the interferance ActionPerformed in order to move the ship and bullet
x += dx;
y += dy;
bx += dx;
by += dy;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = -3;
if (x<=-25){
dx=0;
}
}
if (key == KeyEvent.VK_RIGHT) {
dx = 3;
if (x>=380 ){
dx=0;
}
}
if (key == KeyEvent.VK_UP) {
dy = -3;
if (y<=0 ){
dy=0;
}
}
if (key == KeyEvent.VK_DOWN) {
dy = 3;
if (y>=430 ){
dy=0;
}
}
if(key ==KeyEvent.VK_SPACE){
// bullet shooting and as you can see the y coordinate updates but bullet not moving.
bullet.y--;
System.out.println(bullet.y--);
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 0;
}
if (key == KeyEvent.VK_UP) {
dy = 0;
}
if (key == KeyEvent.VK_DOWN) {
dy = 0;
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void actionPerformed(ActionEvent arg0) {
move();
repaint();
}
int yPost(){
return y;
}
int xPost(){
return x;
}
void doDrawing(Graphics g) {
bullet = new Rectangle(bx, by, 10, 10);
g.setColor(Color.white);
g.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
}
}
This is the main class
import javax.swing.JFrame;
public class MainClass extends JFrame {
private int FrameWidth;
private int FrameHeigh;
private Panel panel;
public MainClass(int width, int height ) {
panel= new Panel();
this.FrameWidth=width;
this.FrameHeigh=height;
setSize(FrameWidth,FrameHeigh);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(panel);
setVisible(true);
}
public static void main(String[] args) {
MainClass m= new MainClass(500, 600);
}
}
create the bullet once ; not inside paint and drawing - inside the constructor;
move this out of
void doDrawing(Graphics g) {
--> remove this from here and into the constructor --> bullet = new Rectangle(bx, by, 10, 10);
also when you update the location of the bullet dont use bx, by and separate variables; just do
bullet.x=....new location
bullet.y=....new location
Inside your key pressed space event, you should create an instance of a bullet. As of right now, you have a member variable Bullet; however it is null since it's never been initialized. That being said, you'll also want to move your bullet--this should be done in your move function.
I see that you have a bx, by, which I'm assuming is suppose to be the bullet's x and y position. However, the rectangle's coordinates never update. Instead of incrementing bx and by, update the rectangle (You'll also want to repaint the rectangle).
import java.awt.Graphics;
import javax.swing.JApplet;
import javax.swing.JPanel;
public class Circle extends JPanel {
int x = 75;
int y = 100;
int diameter = 50;
public void setAnimationY(int y) {
this.y = y;
}
public int getAnimationY() {
return y;
}
public int getDiameter() {
return diameter;
}
public void setDiameter(int startDiameter) {
diameter = startDiameter;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(x, y, diameter, diameter);
}
}
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.Timer;
public class BouncingBall extends JApplet {
private int speed = 5;
private Timer timer;
private Circle draw;
#Override
public void init() {
super.init();
setLayout(new BorderLayout());
draw = new Circle();
add(draw);
timer = new Timer(30, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int y = draw.getAnimationY();
int diameter = draw.getDiameter();
int roof = getHeight();
y += speed;
if (y < 0) {
y = 0;
speed *= -1;
} else if (y + diameter > roof) {
y = roof - diameter;
speed *= -1;
}
draw.setAnimationY(y);
repaint();
}
});
}
#Override
public void start() {
super.start();
timer.start();
}
#Override
public void stop() {
timer.stop();
super.stop();
}
}
I am trying to create a JApplet that contains a ball that is bouncing up and down. So far I have been able to get the ball to go up and down but now I am trying to make the ball more "life-like" so I want the height of the ball to decrease each time the ball bounces until eventually it stops.
I have attempted to do a while loop using the roof variable that I created for the getHeight() method but for some reason when I tried to use it either the ball didn't move at all or the loop had no affect on the ball.
I have also tried a for loop but I ran into the same problem that I got into with the while loop. I believe the problem is that I am not placing this for loop in the correct spot for it to work correctly.
thanks in advance.
Little modifications to your code that can give you some trails:
#Override
public void actionPerformed(ActionEvent e) {
int y = draw.getAnimationY();
int diameter = draw.getDiameter();
int roof = getHeight();
y += speed;
//
// Reduce the ball size at the bottom of the screen
//
if(y + diameter > roof) {
if(diameter > minDiameter) {
diameter -= (roof - y);
} else {
diameter = minDiameter;
}
} else if (diameter < maxDiameter) {
diameter++;
}
draw.setDiameter(diameter);
if (y < 0) {
y = 0;
speed *= -1;
} else if (y + diameter > roof) {
y = roof - diameter;
speed *= -1;
}
// Simulates a little gravity
speed += 0.5;
draw.setAnimationY(y);
repaint();
}
For more realism, the best way would to find an equation that is function of the ball position and a coefficient of hardness for the ball and would give you the ball size.
Well let use continue with #MadProgrammer's solution from your other related question:
In your class of DrawPane we can easily define the height, getAnimationHeight() and setAnimationHeight(int) to control the height decrease as soon as it touches the ground. Please remember that in java left-top co-ordinate is (0, 0) and right-bottom co-ordinate is (getWidth(), getHeight()). Suppose that it starts from height = 0(top). Then it will start from y = height(top) and eventually move to the getHeight()(bottom) of your container. We will increase the height(top y) using setAnimationHeight() by adding an amount(say 30) to current height(which getAnimationHeight() will return) .
So, this little tweak made to #MadeProgrammer's solution in your other question will be the following demo.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
public class Circle extends JApplet {
private int delta = 8;
private Timer timer;
private DrawPane drawPane;
#Override
public void init() {
super.init();
setLayout(new BorderLayout());
drawPane = new DrawPane();
add(drawPane);
timer = new Timer(100, new ActionListener() {
int frameCount = 0;
#Override
public void actionPerformed(ActionEvent e) {
int y = drawPane.getAnimationY();
int diameter = drawPane.getDiameter();
y += delta;
if (y < drawPane.getAnimationHeight()) {
y = drawPane.getAnimationHeight();
delta *= -1;
} else if (y + diameter > getHeight()) {
y = getHeight()- diameter;
delta *= -1;
int animationHeight = drawPane.getAnimationHeight();
animationHeight = animationHeight + (getHeight() - diameter - animationHeight)/2;
drawPane.setAnimationHeight(animationHeight);
if(animationHeight + diameter + 2 >= getHeight())
{
System.out.println("true");
drawPane.setAnimationY(getHeight() - diameter);
repaint();
timer.stop();
return;
}
}
drawPane.setAnimationY(y);
repaint();
}
});
}
#Override
public void start() {
super.start();
timer.start();
}
#Override
public void stop() {
timer.stop();
super.stop();
}
public class DrawPane extends JPanel {
int x = 100;
int y = 0;
int diameter = 50;
int height = 0;
public void setAnimationX(int x) {
this.x = x;
}
public void setAnimationY(int y) {
this.y = y;
}
public void setAnimationHeight(int h)
{
height = h;
}
public int getAnimationHeight()
{
return height;
}
public int getAnimationX() {
return x;
}
public int getAnimationY() {
return y;
}
public int getDiameter() {
return diameter;
}
public void setDiameter(int startDiameter) {
diameter = startDiameter;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(x, y, diameter, diameter);
}
}
}
NOTE: As soon as it touches the bottom finally, you should stop the Timer to get rid of the flickering of the ball. This task is left as an exercise for you.
I'm building a little "pong" game in Java.
I'm trying to add a scorekeeper up top that shows the updated score (+1) everytime the player saves the ball with the paddle.
I'm trying to use a JLabel but the problem is that I can't think of a way to continuously update the JLabel each time the paddle is hit.
Any ideas?
My code:
MainPanel Class (the one with the Paddle and Ball and Label)
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
//import swing.graphics.BounceFrame;
//import swing.graphics.Circle;
public class MainPanel extends JPanel implements ActionListener, KeyListener, Runnable{
public Paddle paddle;
public Ball ball;
public MainPanel(){
ball = new Ball(50, 50, 10); //centerX, centerY, radius
setSize(300, 300);
paddle = new Paddle();
JLabel scoreKeeper = new JLabel("Score" + ball.getScore());
add(scoreKeeper);
Thread thread = new Thread(this);
thread.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D)g;
paddle.draw(g2);
ball.draw(g2);
}
public void actionPerformed(ActionEvent e) {
String direction = e.getActionCommand();
switch(direction){
case "left": Paddle.movePaddleLeft(); break;
case "right": Paddle.movePaddleRight(); break;
}
this.repaint();
}
public void run() {
try {
while(true){
ball.move(getBounds());
repaint();
Thread.sleep(500/30);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 37){
Paddle.movePaddleLeft();
}
if (e.getKeyCode() == 39){
Paddle.movePaddleRight();
}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
}
And my Ball class:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.Random;
public class Ball {
private Ellipse2D ball;
private double radius;
private double ballCircumference;
private Color color;
private double x;
private double y;
private double dx = 5;
private double dy = 5;
private int score = 0;
public int getScore() {
return score;
}
//Boundaries to determine if ball is hit by paddle
private double criticalBoundaryX;
private double criticalBoundaryY1;
private double criticalBoundaryY2;
private double paddleHalfwayPoint;
private boolean inGame = true;
public void recalculateCriticals(){
criticalBoundaryX = Paddle.getYPosition() - ballCircumference;
criticalBoundaryY1 = Paddle.getXPosition()- ballCircumference; //Left boundary
criticalBoundaryY2 = Paddle.getXPosition()+Paddle.getPaddleWidth()+ballCircumference; //Right Boundary
paddleHalfwayPoint = (Paddle.getXPosition()+Paddle.getPaddleWidth())/2;
}
public Ball(int centerX, int centerY, int radius) {
this.x = centerX - radius;
this.y = centerY - radius;
this.radius = radius;
ballCircumference = 2*radius;
Random randomRGB = new Random();
color = new Color(randomRGB.nextInt(255), randomRGB.nextInt(255), randomRGB.nextInt(255));
this.ball = new Ellipse2D.Double(x, y, 2*radius, 2*radius);
}
public void move(Rectangle2D bounds) {
recalculateCriticals();
x += dx;
y += dy;
if (x < bounds.getMinX()) {
x = bounds.getMinX();
dx = -dx;
}
if (x + 2*radius >= bounds.getMaxX()) {
//System.out.println(bounds.getMaxX());
x = bounds.getMaxX() - 2*radius;
dx = -dx;
}
if (y < bounds.getMinY()) {
y = bounds.getMinY();
dy = -dy;
}
if (y > criticalBoundaryX){
if (x < criticalBoundaryY1 || x > criticalBoundaryY2){
inGame = false;
}
if (!inGame && hittingEdge(x))
dx = -dx;
}
if (y > criticalBoundaryX && inGame){ //When it hits the paddle
changeColor();
score++;
y = criticalBoundaryX;
dy = -dy;
}
if (y > bounds.getMaxY()){
System.out.println("Game Over");
System.exit(0);
}
recalculateCriticals();
ball.setFrame(x, y, 2*radius, 2*radius);
}
public boolean onPaddle(double x){
return ((x > Paddle.getXPosition()) && (x < Paddle.getXPosition()+Paddle.getPaddleWidth()) && (y > Paddle.getYPosition()-10));
}
public boolean hittingEdge(double x){
return ((x >= criticalBoundaryY1 && x < paddleHalfwayPoint)
||
(x <= criticalBoundaryY1 && x > paddleHalfwayPoint)); //Return true if x is hitting the side edge of the paddle
}
public void changeColor(){
Random randomColor = new Random();
color = new Color(randomColor.nextInt(255), randomColor.nextInt(255), randomColor.nextInt(255));
}
public void draw(Graphics2D g2) {
g2.setColor(color);
g2.fill(ball);
}
}
The "Java way" of doing this would be to define a listener interface, for example:
public interface BallListener {
void paddleHit();
}
In the Ball class, you should add a field
private List<BallListener> listeners;
as well as methods
public void addBallListener(BallListener l) { listeners.add(l); }
public void removeBallListener(BallListener l) { listeners.remove(l); }
When the paddle is hit, you go:
for (BallListener l : listeners)
l.paddleHit();
The main class should implement the BallListener interface, and register itself with the ball (ball.addBallListener(this)).
This approach also enables you to, when needed, inform other parts of your program about different events that happen to the ball (i.e. add a new method to BallListener for each event you'd like to signal).