how do I detect key presses with just one method in java? - java

I'm trying to paint 6 colors, 10 shapes, a jpeg image, and 3 things that change when a key is pressed in java.
However I'm trying to program all of this in one method. I've done everything else except detecting a key press. I've looked at a lot of examples, but all of them use different methods or classes that work together to detect a key press. But how to do I detect key presses and at the same time change pictures/images in JPanel all in just one method.
I tried to write some code but it doesn't work (nothing shows up on the JPanel/screen) Here's my code so far:
public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(0, 0, 1000, 1000);
BufferedImage photo = null;
try
{
File file = new File("holiday.jfif");
photo = ImageIO.read(file);
}
catch (IOException e)
{
g.drawString("Problem reading the file", 100, 100);
}
g.drawImage(photo,0,0,800,800,null);
g.setColor(Color.BLACK);
g.fillRect(120,300,100,100 );
g.setColor(Color.GREEN);
g.fillOval(270,130,50,100 );
g.setColor(Color.BLUE );
g.fillRect(350,200,100,150 );
g.setColor(Color.PINK);
g.fillOval(460, 270, 50, 50);
g.setColor(Color.GRAY);
g.fillArc(500, 300, 110, 100, 5, 150);
g.setColor(Color.YELLOW);
g.fillRect(500,450,100,100);
g.setColor(Color.YELLOW);
g.fillOval(550,500,100,100);
int[] xpoints = {50,150,20,180};
int[] ypoints = {500,500,550,550};
g.setColor(Color.BLACK);
g.drawPolygon(xpoints,ypoints,4);
int[] xpoint = {250,220,380,350};
int[] ypoint = {500,550,550,500};
g.drawPolygon(xpoint,ypoint,4);
int[] x = {600,500,700};
int[] y = {20,100,100};
g.drawPolygon(x,y,3);
g.setColor(Color.ORANGE);
g.fillRect(10,50,220,30);
g.fillRect(115,80,20,100);
Scanner input = new Scanner(System.in);
String press;
boolean stop = false;
while(!stop)
{
//Scanner input = new Scanner(System.in);
press = input.next();
if (press != null)
{
g.clearRect(115,80,20,100);
g.clearRect(500,450,100,100);
stop = true;
}
}
}

Related

Entity not spawning after being summoned Java

So I am trying to call an entity called Mothership with a texture. What should be happening is that the image appears where the player is (temporary place till it appears). Instead, no matter where I move it, it does not appear.
This dropbox link is to the whole game because it all links together.
https://www.dropbox.com/sh/kuvoxzjf00wa8jf/AAD-MaXXcnHMn4PtW-X_vHcUa?dl=0
I thought maybe it's because of Controller.java, not initialising it but I was getting errors. In the end, I want the mothership to be stationary and appear on the side that the player spawns on. The mothership will lose health from enemy bullets which I am working on at the moment.
But here are the bits that I have been focussing my attention to:
public void render(Graphics g) {
g.drawImage(tex.nmothership, (int) x, (int) y, null);
}
^This is in Mothership.java
public void init(){
requestFocus();
BufferedImageLoader loader = new BufferedImageLoader();
try {
spriteSheet = loader.loadImage("/spriteSheet.png");
background = loader.loadImage("/background.png");
}catch(IOException e) {
e.printStackTrace();
}
tex = new Textures(this);
c = new Controller(tex, this);
p = new Player(200, 200, tex, this, c);
menu = new Menu();
mothership = new Mothership(200, 200, tex);
ea = c.getEntityA();
eb = c.getEntityB();
this.addKeyListener(new KeyInput(this));
this.addMouseListener(new MouseInput());
c.createEnemy(enemy_count);
//e = error
}
^In Game.java (the main engine of the game)
private void getTextures() {
player = ss.grabImage(1, 1, 32, 32);
missile = ss.grabImage(2, 1, 32, 32);
enemy = ss.grabImage(3, 1, 32, 32);
emissile = ss.grabImage(4, 1, 32, 32);
nmothership = ss.grabImage(1, 1, 128, 128);
^In Textures.java - the grabImage is from Spritesheet.java
After some playing around I managed to get the "mothership" to spawn however it has come at the price of commenting out the mothership's physics mechanic. I will make another post about it if I am still having trouble.

Adding music to my sound board project

So I'm creating a soundboard for my CS project using java. The soundboard consists of an 8 piece drum set that is supposed to play its set sound when clicked. I've set the area to be clicked but don't know how to implement sound that'll start when the set area is clicked.
// FinalProjectst.java
// AP Computer ScienceStudent Version
import java.awt.*;
import java.applet.*;
import java.awt.geom.Ellipse2D;
public class FinalProjectst extends Applet
{
Image picture;
Ellipse2D base, bT, snare, lT, rT, hh, lC, rC;
int numColor;
public void init()
{
picture = getImage(getDocumentBase(),"drumSet.jpg");
base = new Ellipse2D.Double (355, 415, 305, 240); //Bass
bT = new Ellipse2D.Double (715, 360, 325, 245); //Bottom Tom
snare = new Ellipse2D.Double ( 35, 410, 290, 200); //Snare
lT = new Ellipse2D.Double (283, 130, 185, 165); //Left Tom
rT = new Ellipse2D.Double (543, 120, 200, 175); //Right Tom
hh = new Ellipse2D.Double ( 0, 225, 250, 150); //High Hat
lC = new Ellipse2D.Double ( 10, 0, 305, 195); //Left Cymbal
rC = new Ellipse2D.Double (765, 0, 505, 275); //Right Cymbal
}
public boolean contains(Event e, int x, int y)
{
if(base.contains(x,y))
numColor = 1;
else if(bT.contains(x,y))
numColor = 2;
else if(snare.contains(x,y))
numColor = 3;
else if(lT.contains(x,y))
numColor = 4;
else if(rT.contains(x,y))
numColor = 5;
else if(hh.contains(x,y))
numColor = 6;
else if(lC.contains(x,y))
numColor = 7;
else if(rC.contains(x,y))
numColor = 8;
else
numColor = 9;
repaint();
return true;
}
public void paint(Graphics g)
{
g.drawImage(picture, 0, 0, this);
}
}
There are a lot of different ways to play a sound but for example you could do something like this:
public static void playSound(File soundfile) throws LineUnavailableException, UnsupportedAudioFileException, IOException{
AudioInputStream audioInputStream = null;
audioInputStream = AudioSystem.getAudioInputStream(soundfile);
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
}
This code will play wav files without a problem and I think that it will also play other types of sound files, but I am not sure what sound types it will play and what sound types it will not.
I hope this help :)
EDIT:
As you can see there are a lot of exceptions that can be thrown from this code, so you probably want to handle them in an appropriate way.

Java SWT GC not drawing text on Canvas

I have the following code:
final Canvas canvas = new Canvas(mainshell, SWT.NO_REDRAW_RESIZE);
canvas.setBounds(0, 0, mainshell.getSize().x, mainshell.getSize().y);
canvas.setBackgroundImage( new Image(display, "BlueBack.jpg" ));
canvas.setFont(font);
GC gc = new GC(canvas);
gc.drawText("Test", 0, 0, true);
gc.dispose();
canvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
e.gc.drawText("String", 170, 30, true);
e.gc.drawText("Another Unimportant String", 80, 90, true);
int I = 140;
int i = 1;
String[] strings = Stuff.getUnimportantStringArray();
if(strings != null)
for(String string : strings){
e.gc.drawText( i + " " + string , 120, I, true);
I += 50;
i++;
}
}
});
The code that I am having the problem with is this:
GC gc = new GC(canvas);
gc.drawText("Test", 0, 0, true);
gc.dispose();
The gc.drawText(); is not drawing the String "Test" on the canvas as I expected it would.
Here is my Question:
Why is the gc.drawText("Test", 0, 0, true"); not working, but the e.gc.drawText("String", 170, 30, true); inside the PaintListeneris working ?
The paintControl() method is called whenever the canvas needs to be redrawn which could happen any number of times. For example, the PaintListener is used when the canvas is resized (try putting a breakpoint on paintControl(), resize the window, and see for yourself). All drawing you need to do should be in the PaintListener.
Also, you shouldn't use setBounds() here. Use a layout instead:
mainShell.setLayout(new FillLayout());

Swing: moving two graphics at the same time

I am working on Air Hockey Game for my midterm project.
I have problem with handling two graphics, in this case two handles each of them consists of 3 circles.
I can move only one handle because of keyPressed method.
Another problem is that I can't limit the moving domain, for example when you pressed → the red handle can go beyond the frame width.
I know first problem is related to thread, but I've studied this subject from last week.
My problems are in this class:
public class StartGamePanel extends JPanel implements KeyListener, ActionListener {
double xCircle1 = 200;
double yCircle1 = 100;
double xCircle2 = 200;
double yCircle2 = 700;
double velX = 0, velY = 0;
public StartGamePanel() {
Timer t = new Timer(5, this);
t.start();
addKeyListener(this);
setFocusable(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g.setColor(new Color(51, 153, 255));
g.fillRoundRect(5, 5, 485, 790, 10, 10);
addKeyListener(this);
Graphics2D southArc = (Graphics2D) g;
southArc.setColor(Color.WHITE);
southArc.setStroke(new BasicStroke(3));
southArc.drawArc(98, 640, 300, 300, 0, 180);
//
Graphics2D northArc = (Graphics2D) g;
northArc.setColor(Color.WHITE);
northArc.setStroke(new BasicStroke(3));
northArc.drawArc(98, -143, 300, 300, 180, 180);
Graphics2D line = (Graphics2D) g;
line.setStroke(new BasicStroke(3));
line.setColor(Color.white);
line.drawLine(6, 395, 488, 395);
Graphics2D dot = (Graphics2D) g;
dot.setColor(Color.black);
for (int j = 10; j < 800; j += 20) {
for (int i = 6; i < 502; i += 20) {
dot.drawLine(i, j, i, j);
}
}
Graphics2D circle1 = (Graphics2D) g;
circle1.setColor(new Color(255, 51, 51));
Shape theCircle = new Ellipse2D.Double(xCircle1 - 40, yCircle1 - 40, 2.0 * 40, 2.0 * 40);
circle1.fill(theCircle);
Graphics2D circle2 = (Graphics2D) g;
circle2.setColor(new Color(255, 102, 102));
Shape theCircle2 = new Ellipse2D.Double(xCircle1 - 35, yCircle1 - 35, 2.0 * 35, 2.0 * 35);
circle2.fill(theCircle2);
Graphics2D circle3 = (Graphics2D) g;
circle3.setColor(new Color(255, 51, 51));
Shape theCircle3 = new Ellipse2D.Double(xCircle1 - 20, yCircle1 - 20, 2.0 * 20, 2.0 * 20);
circle3.fill(theCircle3);
Graphics2D circleprim = (Graphics2D) g;
circleprim.setColor(new Color(0, 51, 102));
Shape theCircleprim = new Ellipse2D.Double(xCircle2 - 40, yCircle2 - 40, 2.0 * 40, 2.0 * 40);
circleprim.fill(theCircleprim);
Graphics2D circle2prim = (Graphics2D) g;
circle2prim.setColor(new Color(0, 102, 204));
Shape theCircle2prim = new Ellipse2D.Double(xCircle2 - 35, yCircle2 - 35, 2.0 * 35, 2.0 * 35);
circle2prim.fill(theCircle2prim);
Graphics2D circle3prim = (Graphics2D) g;
circle3prim.setColor(new Color(0, 51, 102));
Shape theCircle3prim = new Ellipse2D.Double(xCircle2 - 20, yCircle2 - 20, 2.0 * 20, 2.0 * 20);
circle3prim.fill(theCircle3prim);
Graphics2D ball = (Graphics2D) g;
ball.setColor(new Color(224, 224, 224));
Shape theball = new Ellipse2D.Double(200 - 20, 400 - 20, 2.0 * 20, 2.0 * 20);
ball.fill(theball);
Graphics2D ball2 = (Graphics2D) g;
ball2.setColor(new Color(160, 160, 160));
Shape theball2 = new Ellipse2D.Double(200 - 15, 400 - 15, 2.0 * 15, 2.0 * 15);
ball2.fill(theball2);
Graphics2D goal = (Graphics2D) g;
goal.setColor(Color.BLACK);
goal.fill3DRect(100, 0, 300, 10, true);
Graphics2D goal2 = (Graphics2D) g;
goal2.setColor(Color.BLACK);
goal2.fill3DRect(100, 790, 300, 10, true);
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
xCircle1 += velX;
yCircle1 += velY;
}
#Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
velY = -2;
velX = 0;
}
if (code == KeyEvent.VK_DOWN) {
velY = 2;
velX = 0;
}
if (code == KeyEvent.VK_LEFT) {
if (xCircle1 < 0) {
velY = 0;
velX = 0;
} else {
velY = 0;
velX = -2;
}
}
if (code == KeyEvent.VK_RIGHT) {
if (xCircle1 > 200) {
velY = 0;
velX = 0;
}
velY = 0;
velX = 2;
}
}
#Override
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
velY = 0;
velX = 0;
}
if (code == KeyEvent.VK_DOWN) {
velY = 0;
velX = 0;
}
if (code == KeyEvent.VK_LEFT) {
velY = 0;
velX = 0;
}
if (code == KeyEvent.VK_RIGHT) {
velY = 0;
velX = 0;
}
}
#Override
public void keyTyped(KeyEvent e) { }
}
Thanks!
Your key listener should be as quick as possible so it does not block following key events. Since several people press keys almost at the same time, this situation is common in games.
So the advice would be to use separate thread to listen for key presses which will quickly add events to a queue. This queue then will be processed on EDT(Swing main thread) and paint the results.
You can check out the KeyboardAnimation.java example found in Motion Using The Keyboard. It attempts to explain why Key Bindings are preferred over using a KeyListener.
The example code will animate two images. The left image controlled by W, A, S, D and the right image by Up, Down, Left and Right arrow keys. It also keeps the images within the window bounds. The code is not an actual game, it was just designed to show one way to use configurable Key Bindings.
You might want to also want to change the way the keypress's are handled. At the moment (I think) your only detecting one key down at a time.
You probably need to have an array for "heldkeys" and every time a key is down, add to that array. When a key is released, subtract that key from it.
Then, at a interval, check what keys are in the "heldkeys" array and act on them all.
At least, you will probably need something like this if you plan to have two players. (who both should be able to press keys at the same time).
I don't know Swing well enough to give you exact code, but it will be something like;
//an array of numbers to hold the key-codes of the keys currently held down
HashSet<Integer> HeldKeys = new HashSet<Integer>();
#Override
public void keyDown(KeyEvent e) {
// add key to keys currently held down
HeldKeys.add(e.getKeyCode());
}
#Override
public void keyUp(KeyEvent e) {
//remove key from list of things currently held
HeldKeys.remove(e.getKeyCode());
}
#Override
public void keyPress(KeyEvent e) {
Iterator<Integer> kit = HeldKeys.iterator();
//we loop over every key currently held down, running actions for them if
//there is any assigned.
//For example, one button might move a sprite on the left down
//Another might move a sprite on the right. One, the other, or both should be
//able to all move without waiting for the other.
while (kit.hasNext()) {
int keycode = kit.next();
if (keycode==48){
//do stuff if key with code 48 is held
//(move one of the circles, etc)
}
if (keycode==46){
//do stuff if key with code 46 is held
}
//...etc, for any number of keys you want to do different things for.
}
}
Note; With this method you are not detecting a keypress as one thing, but rather detecting both the key being held down, and then the key being released as separate events.
As people wont hit the keys at the exact same time, this lets you detect lots of keys at once.
This code is off the top of my head, Java, but I have a gwt background, so the names for "keydown" and "keyup" etc might be different.
The "keypress" event in gwt will repeat automatically, if that's not the case in Swing you might need to use a Timer instead, running at an interval. (you might prefer this anyway as its a bit more controllable).

Refresh text in Applet

I am doing this small race between two cars, in a java applet.
Just two pictures moving at random speed. I am calculating the distance between current position and the finish line, and you are suppose to be able to see the distance in the upper corner.
The thing is I am not able to refresh the text field, instead it just applies a new layer on top of the old number so it is almost impossible to read.
Here are pictures to demonstrate my problem.
I thought I would be able to solve it by creating the blue rectangle at the start of each loop but that does not seem to solve it.
public void action(){
Random rand = new Random();
boolean race = true;
int x1 =500, y1 = 233;
int x2 = 500, y2 = 333;
int speed1 = rand.nextInt(15) + -16;
int speed2 = rand.nextInt(15) + -16;
int finishline = 30;
Text winnerBlue = new Text("Winner: BLUE",new Font("SansSerif",Font.BOLD,20), Color.blue,Color.white);
Text winnerRed = new Text("Winner: RED",new Font("SansSerif",Font.BOLD,20), Color.red,Color.white);
//background
Text text =null;
Text text2 = null;
window.fillRect(0, 0, 600, 400, Color.GREEN);
//track 1
window.fillRect(20, 330, 550, 39, Color.gray);
//track2
window.fillRect(20, 230, 550, 39, Color.gray);
//Finish line
window.fillRect(40, 210, 10, 180, Color.BLACK);
while(race){
text = new Text(Integer.toString(x1),new Font("Courier",Font.BOLD,20), Color.WHITE);
text2 = new Text(Integer.toString(x2),new Font("SansSerif",Font.BOLD,20), Color.WHITE);
window.fillRect(0, 0, 70, 50, Color.blue);
window.fillRect(70, 0, 70, 50, Color.red);
window.showImage(text, 0, 0);
window.showImage(text2, 70, 0);
window.showImage(car1.getImage(), x1, y1);
window.showImage(car2.getImage(), x2, y2);
car1.moveTo(x1 += speed1, y1);
car2.moveTo(x2 += speed2, y2);
window.pause(50);
if(x1 <= (finishline ) ){
speed1 = 0;
speed2 = 0;
window.showImage(winnerBlue, 200, 200);
race = false;
}
if(x2 <= (finishline)){
speed2 = 0;
speed1 = 0;
window.showImage(winnerRed, 200, 200);
race = false;
}
}
}
}
For the two screen shots and supplied code snippt, it's clear that you don't understand how painting works in Swing/AWT.
Do NOT ever, maintain any kind of refernce to the Graphics context out side of the paintXxx methods.
The paint methods perform a number of very important steps to prepare the Graphics context for painting
Start by taking a look through Performing Custom Painting

Categories

Resources