So I have a little piece of code here. What the code is supposed to do:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class squareMovingUsingArrowKeys extends JPanel implements ActionListener,KeyListener {
static int x;
static int y;
static double acceleration=0.3;
static int originSpeed;
static int actualSpeed;
static boolean a=false;
Timer timer;
squareMovingUsingArrowKeys() {
x = 0;
y = 0;
acceleration = 0.3;
actualSpeed = 1;
}
#SuppressWarnings("deprecation")
public void keyPressed(KeyEvent e) {
a = true;
System.out.println(actualSpeed);
actualSpeed+=acceleration;
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
x -= actualSpeed;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
x += actualSpeed;
}
if (e.getKeyCode() == KeyEvent.VK_UP) {
y -= actualSpeed;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
y += actualSpeed;
}
//first call move to update x and y and later repaint that JPanel
move(x, y);
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(125,125,255));
g.fillRect(x, y, 20, 20);
g.setColor(new Color(100,255,100));
g.fillOval(x, y, 20, 20);
if(x>=500){
x=500;
}else if(y>=500){
y=500;
}else if(x<=0){
x=0;
}else if(y<=0){
y=0;
}
}
public void start() {
keyPressed(null);
paintComponent(null);
}
public static void main(String[] args) {
JFrame f = new JFrame("Moving");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
squareMovingUsingArrowKeys m = new squareMovingUsingArrowKeys();
f.add(m);
f.setSize(500, 500);
f.setVisible(true);
f.addKeyListener(m);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
originSpeed = 1;
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
- Be able to "accelerate" as you hold a button
Stop when the x or y is at 500
Move in secondary directions
But obviously, it doesn't work.
How can I fix this?
Your actualSpeed variable is an int and you are trying to add 0.3 to it which is a double and less than 1. If it would have been greater than 1 let's say 1.2, then java would have added 1 to your actualSpeed.
Change type of actualSpeed to double and it will work as you cannot add doubles or floating point to an int.
I will also recommend you to read about primitive data types of Java.
For stopping when x = 500 or y = 500. You need to use an if statement inside your keyhandler which checks that both x && y are less than 500 else it won't accelerate. For moving diagonally. Your green dot does move diagonally on my system.
Related
I have a rectangle in which I wanted to rotate. So I just made it that it switches the width and the height every time I press a key. But that key also moves the rectangle downwards, so after clicking again it rotates back to its former position.
So I want to know how I can make it only rotate once and the then after that if press downwards(the key which makes it rotate) again it just moves downwards but doesn't rotate it again.
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class paint extends JLabel implements KeyListener {
int x = 1;
int y = 1;
int velocity = 20;
int w = 200;
int h = 100;
int temp;
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.BLACK);
g.setColor(Color.RED);
g.fillRect(x, y, w, h);
repaint();
}
//this is the section i am talking about.
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
y += velocity;
System.out.println(y);
//the next three lines rotate the rectangle
temp = w;
w = h;
h = temp;
if (y > 261) {
y = 1;
}
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
x += velocity;
System.out.println(x);
if (x > 591) {
x = 1;
}
} else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
x -= velocity;
System.out.println(x);
if (x < 1) {
x = 591;
}
} else if (e.getKeyCode() == KeyEvent.VK_UP) {
y -= velocity;
System.out.println(y);
if (y < 1) {
y = 271;
}
}
}
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
There are no errors or sth, just a transparent screen (It will copy the background) and a drawn oval, but whenever i try to type an arrow key in the keyboard it won't work. I have added the KeyListener and extended the class to JFrame, but it still does nothing. I know it is just beginner stuff, but I am a beginner myself, and this has been bugging me :/ . Also, I have also used repaint(); , but still it re-renders the background? Thanks for the help in advance!
package JavaMain;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
public class javamain extends JFrame {
int x, y;
private static final long serialVersionUID = 1L;
public class AL extends KeyAdapter {
private int keycode;
#SuppressWarnings("static-access")
public void keypress(KeyEvent event) {
keycode = event.getKeyCode();
if (keycode == event.VK_LEFT) {
x -= 10;
}
if (keycode == event.VK_RIGHT) {
x += 10;
}
if (keycode == event.VK_UP) {
y -= 10;
}
if (keycode == event.VK_DOWN) {
y += 10;
}
}
public void keyrelease(KeyEvent e) {
}
}
public javamain() {
addKeyListener(new AL());
setTitle("Statistic");
setSize(600, 800);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
x = 200;
y = 200;
}
public void paint(Graphics g) {
g.fillOval(x, y, 20, 20);
repaint();
}
public static void main(String[] args) {
new javamain();
}
}
The error is with your KeyListener.
The AL class isn't using the right method names.
Should be keyPressed and keyReleased as far as I am aware.
private class AL extends KeyAdapter {
public void keyPressed(KeyEvent event) {
int keycode = event.getKeyCode();
if (keycode == KeyEvent.VK_LEFT) {
x -= 10;
}
if (keycode == KeyEvent.VK_RIGHT) {
x += 10;
}
if (keycode == KeyEvent.VK_UP) {
y -= 10;
}
if (keycode == KeyEvent.VK_DOWN) {
y += 10;
}
}
public void keyReleased(KeyEvent e) {
}
}
Without changing any of your other code this seems to work.
I have a very strange problem.
I am making a simple 2d platformer using Java.
The collision detection with the player and a platform, doesn't work.
But the strange thing is, when I print something to the screen to see if the collision if-statement is executed, the collision works o_O
Maybe it's a bit confusing, please see my code.
The Main class(which is good I think):
import javax.swing.*;
public class Main extends JFrame{
private static final long serialVersionUID = 1L;
GameClass gc = new GameClass();
public Main(){
setSize(gc.WIDTH,gc.HEIGHT);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Flying GoatZ!");
add(new GameClass());
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
GameClass class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
public class GameClass extends JPanel implements ActionListener, KeyListener, MouseListener{
//OBJECTS
Text text = new Text();
openImages open_img = new openImages();
Random ran = new Random();
//VARIABLES
static final long serialVersionUID = 1L;
final int WIDTH = 800;
final int HEIGHT = 600;
int goatx = WIDTH/2;
int goaty = 350;
int goatspeed = 0;
int fallspeed = 15;
int maxy = 150;
boolean up = false;
boolean flying = true;
ArrayList<Integer> xes = new ArrayList<Integer>();
ArrayList<Integer> yes = new ArrayList<Integer>();
//FPS SETTER AND KEYLISTENERS
public GameClass(){
Timer time = new Timer(15, this);
time.start();
this.addKeyListener(this);
this.setFocusable(true);
open_img.openImage();
}
public void update(){
Collision();
goatx += goatspeed;
if(up){
if(goaty > maxy){
goaty -= 5;
}else{
up = false;
}
}else
if(goaty < 350)
goaty += fallspeed;
}
public void print(String msg){
System.out.println(msg);
}
public void platformDrawing(Graphics g,int x,int y,int x1,int y1, int x2, int y2){
g.setColor(Color.RED);
g.drawImage(open_img.block,x, y, null);
g.drawImage(open_img.block,x1, y1, null);
g.drawImage(open_img.block,x2, y2, null);
xes.addAll(Arrays.asList(x,x1,x2));
yes.addAll(Arrays.asList(y,y1,y2));
}
//HERE IS THE COLLISION METHOD(I NEED THE PLAYER TO STAND STILL WHEN IT IS ON THE PLATFORM.
public void Collision(){
for(int x : xes){
for(int y : yes){
if( ( (goatx > x-20) && (goatx < (x + 150)) ) && ( (goaty+open_img.goat.getHeight(null)) <= y ) ){
//print("TEST");
fallspeed = 0;
}else{
fallspeed = 10;
}
}
}
}
//ALL TEH DRAWING
public void paintComponent(Graphics g){
//MAP
g.setColor(Color.CYAN);
g.fillRect(0,0,WIDTH,HEIGHT);
g.setColor(Color.ORANGE);
g.fillRect(0, HEIGHT-100, WIDTH, 100);
g.setColor(Color.GREEN);
g.fillRect(0, HEIGHT-125, WIDTH, 25);
//PLAYER & PLATFORMS
platformDrawing(g,50,350,300,350,600,350);
g.drawImage(open_img.goat, goatx, goaty, null);
g.dispose();
}
//THIS IS EXECUTED EVERYTIME
public void actionPerformed(ActionEvent e){
update();
repaint();
}
//KEY DETECTION
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT){
goatspeed = -5;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
goatspeed = 5;
}
if(e.getKeyCode() == KeyEvent.VK_SPACE){
if(flying){
flying = false;
up = true;
}
}
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT){
goatspeed = 0;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
goatspeed = 0;
}
if(e.getKeyCode() == KeyEvent.VK_SPACE){
flying = true;
}
}
//SOME STUFF THAT YOU HAVE TO IGNORE LEL
public void keyTyped(KeyEvent e){}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
}
I don't understand why a print statement can make the difference...
Any help is appreaciated, thanks!
Oh, and sorry for bad English or unclear question.
I'm coding a game so that when you hold D the character moves right and when you hold S the character moves left. The program works just as it should, with one exception. As I'm moving the character (and the character moves perfectly fine), java keeps throwing the error "java.util.ConcurrentModificationException". I did some research and learned that I cannot be adding to the ArrayList "keys" and be iterating it at the same time. With that said, how do I edit the code to still have the character move seamlessly as he is now? This is the only way I know of to make sure the character moves at the same steady pace the second you hold a key down, not take a quick movement, pause, and then continue with the motion.
package LevelEditor;
import java.awt.Canvas;
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.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;
import java.util.ArrayList;
import java.util.Iterator;
public class LevelEditor extends Canvas implements KeyListener, Runnable, MouseListener, MouseMotionListener{
private Object[][] grid = new Object[50][50];
private Graphics bufferGraphics = null; //The graphics for the back buffer
private BufferStrategy bufferStrategy = null;
private Thread thread;
private boolean running;
private int selectedBlock = 0;
private int mouseX;
private int mouseY;
private int playerX;
private int playerY;
private ArrayList<Integer> keys = new ArrayList<Integer>();
Iterator itr;
Player player1;
public LevelEditor(Dimension size){
//Constructor
this.setPreferredSize(size);
this.addKeyListener(this);
this.thread = new Thread(this);
this.addMouseListener(this);
this.addMouseMotionListener(this);
running = true;
mouseX = 0;
mouseY = 0;
playerX = 0;
playerY = 0;
itr = keys.iterator();
}
public void paint(Graphics g){
if (bufferStrategy == null){
this.createBufferStrategy(2);
bufferStrategy = this.getBufferStrategy();
bufferGraphics = bufferStrategy.getDrawGraphics();
player1 = new Player(playerX, playerY);
this.thread.start();
}
}
#Override
public void run() {
//This is what runs when level editor is running
while (running){
//Program's logic
DoLogic();
Draw();
DrawBackbufferToScreen();
Thread.currentThread();
try{
Thread.sleep(10);
}
catch(Exception e){
e.printStackTrace();
}
}
}
public void DoLogic(){
}
public void Draw(){
//clear secondary screen
bufferGraphics = bufferStrategy.getDrawGraphics();
try{
bufferGraphics.clearRect(0, 0, this.getSize().width, this.getSize().height);
//this is where everything will be drawn to back buffer
for (int x = 0; x < grid.length; x++){
for(int y = 0; y < grid[x].length; y++){
Object o = grid[x][y];
if (o instanceof Block){
Block blocktoDraw = (Block)o;
blocktoDraw.draw(bufferGraphics);
}
}
}
Block.getBlock(selectedBlock, mouseX, mouseY).draw(bufferGraphics);
player1.draw(bufferGraphics);
for (Integer x : keys){
if(x == 68 && itr.hasNext()){
playerX += 5;
player1.updatePlayer(playerX, playerY);
player1.draw(bufferGraphics);
itr.next();
itr.remove();
}
if (x == 65 && itr.hasNext()){
playerX -= 5;
player1.updatePlayer(playerX, playerY);
player1.draw(bufferGraphics);
itr.next();
itr.remove();
}
}
}
catch(Exception e){
e.printStackTrace();
}
finally{
bufferGraphics.dispose();
}
}
public void DrawBackbufferToScreen(){
bufferStrategy.show();
Toolkit.getDefaultToolkit().sync();
}
#Override
public void mouseReleased(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
mouseX = (mouseX / 25);
mouseY = (mouseY / 25);
if (e.getModifiers() == 16){
grid[mouseX][mouseY] = Block.getBlock(selectedBlock, mouseX, mouseY);
}
else if (e.getModifiers() == 4){
grid[mouseX][mouseY] = Block.getBlock(100, mouseX, mouseY);
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
keys.clear();
}
#Override
public void keyPressed(KeyEvent e) {
keys.add(e.getKeyCode());
}
public void mouseMoved(MouseEvent e) {
this.mouseX = e.getX() / 25;
this.mouseY = e.getY() / 25;
}
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseDragged(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
mouseX = (mouseX / 25);
mouseY = (mouseY / 25);
if(e.MOUSE_DRAGGED == 506 && e.getModifiers() == 16){
grid[mouseX][mouseY] = Block.getBlock(selectedBlock, mouseX, mouseY);
}
else if (e.MOUSE_DRAGGED == 506 && e.getModifiers() == 4){
grid[mouseX][mouseY] = Block.getBlock(100, mouseX, mouseY);
}
}
}
Using an Iterator is the wrong model here: you aren't actually iterating through the list, you are just looking to see if you have an element, and then processing it if you have something.
A better fit is to use a queue - particularly, some sort of concurrent queue, e.g. java.util.concurrent.BlockingQueue, since you are modifying it and reading it in different threads.
You can add key codes into this using queue.add(e.getKeyCode()), and remove them using queue.poll() (or queue.peek()), which returns a null value if there is nothing in the queue (akin to itr.hasNext() being false).
how would I adjust the speed at which the ghost moves in this code? Is the required code already there and i just need to change values? or do I need to add anything? I am fairly new to coding so please try to put this in easiest form possible. thank you.
package basicgame;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class JavaGame extends JPanel {
int x, y;
// private Image dbImage;
//private Graphics dbg;
Image ghost;
Image bg;
public class AL extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
if (x <= 8)
x = 8;
else
x += -5;
}
if (keyCode == e.VK_RIGHT) {
if (x >= 435)
x = 435;
else
x += +5;
}
if (keyCode == e.VK_UP) {
if (y <= 18)
y = 18;
else
y += -5;
}
if (keyCode == e.VK_DOWN) {
if (y >= 325)
y = 325;
else
y += +5;
}
}
public void keyReleased(KeyEvent e) {
}
}
public JavaGame() throws Exception {
// Load images
ghost = ImageIO.read(new File("ghost.gif"));
bg = ImageIO.read(new File("myBkg.PNG"));
setFocusable(true);
// Game properties
addKeyListener(new AL());
x = 10;
y = 10;
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
repaint();
}
};
Timer timer = new Timer(10,al);
timer.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// here, you have a 'drawimage' command for each object you're moving
// if you have 2 players, you have another drawImage for that one
// if you have a bullet, you have another for it. You have to keep
//track of each object's x,y coordinates and then draw the image at that position.
//you'll need some collision detection in there to see if bullets/players are
//in the same position and then act accordingly.
g.drawImage(bg, 0, 0, null);
g.drawImage(ghost, x, y, this);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
JFrame f = new JFrame("Java Game");
f.setSize(500, 500);
f.setResizable(false);
f.setVisible(true);
f.setBackground(Color.GRAY);
f.setContentPane(new JavaGame());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
The position is stored in the variables x and y. The "speed" of movement is described simply by the rate of change of these variables on keypress; a brief look at the code shows that this "speed" is set, rather clumsily, to 5. It appears in four different places--once for each direction vector. To change the "speed", you can just change all of these occurrences, but remember that if you forget to change some of them, the object will move at different speeds in different directions!
You could vastly improve this code by replacing all of your magic numbers with named variables. This includes not only the "speed", but also the movement boundaries: 8, 18, 435, and 325. Put these named variables inside the AL class or maybe the JavaGame class, depending on where they need to be available.
There's also an unrelated bug that I want to mention. Your current code will allow you to move out-of-bounds, and then on a subsequent keypress, move in the opposite direction indicated due to the "clipping". For example, say x = 10. If you press Left, you'll change x to 5. If you then press Left again, the boundary condition will trigger and you'll move right, setting x to 8. This is probably not desirable, so you should apply the movement first, then clip to the boundary.
Your AL class (consider a more descriptive name for this as well...) might then look something like this:
public class AL extends KeyAdapter {
private static final int SPEED = 5; // Controls the movement speed in all directions
// Variables controlling the movement boundaries
private static final int BOUND_LEFT = 8;
private static final int BOUND_RIGHT = 435;
private static final int BOUND_BOTTOM = 18;
private static final int BOUND_TOP = 325;
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
x -= SPEED; // Move left
if (x <= BOUND_LEFT) {
x = BOUND_LEFT; // If movement placed us out of bounds, move to boundary instead
}
}
if (keyCode == e.VK_RIGHT) {
x += SPEED;
if (x >= BOUND_RIGHT) {
x = BOUND_RIGHT;
}
}
if (keyCode == e.VK_UP) {
y += SPEED;
if (y >= BOUND_TOP) {
y = BOUND_TOP;
}
}
if (keyCode == e.VK_DOWN) {
y -= SPEED;
if (y <= BOUND_BOTTOM) {
y = BOUND_BOTTOM;
}
}
}
public void keyReleased(KeyEvent e) {
}
}