I have been working on a basic Applet (not JApplet, I don't know why my instructor told me to use AWT...). It's a simple game that has a ball bouncing across the screen, collecting dots.
I recently added a menu, and it seems to be all working ok, but when I press "play" the game starts, and freezes on the first frame. I will paste a skeleton of the code below, cutting out what I assume to be irrelevant to the question. Please forgive my Syntax and perhaps ignorance as I have only been programming for a week or two.
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Menu;
import java.awt.event.MouseEvent;
public class StartingPoint extends Applet implements Runnable
{
private Graphics doubleG;
Ball b;
boolean gameOver = false;
Menu menu = new Menu();
private enum STATE
{
MENU,
GAME,
};
public static STATE State =STATE.MENU;
// more irrelevant variables below. will comment "blah blah" when cut has been made.
#Override
public void init()
{
setSize(800,600);
// blah blah
}
#Override
public void start()
{
b = new Ball();
// blah blah
Thread thread = new Thread(this);
thread.start();
}
#Override
public void run()
{
if(State == STATE.GAME)
{
while(true)
{
b.update(this);
// blah blah
repaint();
try
{
Thread.sleep(17);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
else if(State == STATE.MENU)
{
while(true)
{
repaint();
try
{
Thread.sleep(17);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public void update(Graphics g)
{
if(i == null)
{
i = createImage(this.getSize().width, this.getSize().height);
doubleG = i.getGraphics();
}
doubleG.setColor(getBackground());
doubleG.fillRect(0, 0, this.getSize().width, this.getSize().height);
doubleG.setColor(getForeground());
paint(doubleG);
g.drawImage(i, 0, 0, this);
}
public void paint (Graphics g)
{
if(State == STATE.GAME)
{
b.paint(g);
//blah blah
}
else if(State ==STATE.MENU)
{
menu.render(g);
}
}
#Override
public void mouseClicked(MouseEvent e)
{
if(mouseIn)
{ //mouseIn is a boolean that checks if Try Again is clicked on lose
if(b.getScore() == -1)
{
b = null;
b = new Ball();
b.setScore(0);
}
if(State == STATE.MENU)
{
if(menu.isPlayb() == true)
{ //playb=boolean to check if "play" is clicked on menu.
State = STATE.GAME;
menu.setPlayb(false);
}
}
}
}
}
It's still quite long sorry, I tried to cut as much as possible.
Could someone please give me a hand here? It would be much appreciated.
Here is some more info about the way the program behaves:
If the initial state is set to game, the applet runs just as it did without a menu.
There is no error given when the game pauses after the play button is pushed.
I have a guess that the problem lies in that after the play button sets the state to STATE.GAME, the beginning of the code sets it back to menu again. No idea how accurate of a guess this is though, as I have tried many ways of avoiding writing STATE.MENU at the beginning of the code, to no different result. (I tried booleans, and If/else).
Please help if you can!
Thanks so much.
Also, if you need any more info, I will provide :)
Thanks for trying to help everyone! After all the effort of attempting to solve the problem, the answer was simple. I just needed to run my start method again when the play button is pushed....
Thanks :)
Related
The simple Problem: i have a RaspPi3 hooked to a TV (via HDMI) and on that a java Swing application in fullscreen (remote client to show simple text as a slide show). The TV, however, goes into standby after ~60 seconds, but only if my app is running. If i simply display the desktop the TV just stays alive.
The Question is: does a fullscreen swing app mess with the HDMI signal, so that the TV thinks there is nothing more to show and shuts down? (Or is there something wrong with the way i approach the function of displaying text? See code below*)
Or is it a problem with the TV because the signal stays the same and doesnt change or isn't strong enough over ~60 seconds (too much "blank" space because the screen is mostly black)?
Note: My app does work as intended on a pure functionally basis. This standby behavior is a "bug" that i did not expect.
I don't have that deep insight of the HDMI spec, so if anyone could give me a hint on how to solve this problem, i would appreciate it.
This is my first question and i decided to ask it because i didnt found any similar problem to mine. I am not entirely sure if this question is to specific, so i apologize in advance if it is.
*Code:
public GUIController()
{
Statics.GUIC = this;
jf = new JFrame("SP-MultiMonitor#arm " + Statics.VERSION_INFOS);
jf.setUndecorated((Statics.PROPERTIES.getProperty("p.undecorated").equals("true")));
jf.setAlwaysOnTop(true);
jf.setLocation(Integer.parseInt(Statics.PROPERTIES.getProperty("p.pos.x")), Integer.parseInt(Statics.PROPERTIES.getProperty("p.pos.y")));
jf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Container cp = jf.getContentPane();
MyCanvas tl = new MyCanvas();
tl.setBackground(Color.BLACK);
cp.add(tl);
cp.setBackground(Color.BLACK);
jf.setSize(Integer.parseInt(Statics.PROPERTIES.getProperty("p.width")), Integer.parseInt(Statics.PROPERTIES.getProperty("p.height")));
jf.setVisible(true);
t = 0;
timer = new Timer(100, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
//check cmd
switch (Statics.PRESENTATION_CMD)
{
case Statics.REND_CMD_EMPTY:
Statics.PRESENTATION_CMD = Statics.REND_CMD_RUN;
break;
case Statics.REND_CMD_RUN:
break;
case Statics.REND_CMD_START:
tl.repaint();
Statics.PRESENTATION_CMD = Statics.REND_CMD_RUN;
break;
case Statics.REND_CMD_STOP:
Statics.PRESENTATION_CMD_ADD = null;
tl.repaint();
Statics.PRESENTATION_CMD = Statics.REND_CMD_EMPTY;
break;
case Statics.REND_CMD_NEXT:
Statics.PRESENTATION_CMD = Statics.REND_CMD_RUN;
break;
case Statics.REND_CMD_PREV:
Statics.PRESENTATION_CMD = Statics.REND_CMD_RUN;
break;
case Statics.REND_CMD_GOTO:
Statics.PRESENTATION_CMD = Statics.REND_CMD_RUN;
break;
}
}
});
jf.addWindowListener(new WindowListener()
{
#Override
public void windowOpened(WindowEvent e)
{
}
#Override
public void windowClosing(WindowEvent e)
{
timer.stop();
}
#Override
public void windowClosed(WindowEvent e)
{
}
#Override
public void windowIconified(WindowEvent e)
{
}
#Override
public void windowDeiconified(WindowEvent e)
{
}
#Override
public void windowActivated(WindowEvent e)
{
}
#Override
public void windowDeactivated(WindowEvent e)
{
}
});
timer.setInitialDelay(1000);
timer.start();
}
public void toggleVisibility()
{
jf.setVisible(!jf.isVisible());
}
}
class MyCanvas extends JComponent
{
int fontSize = 50;
Font font = new Font("Calibri", Font.PLAIN, fontSize);
#Override
public void paintComponent(Graphics g)
{
if (g instanceof Graphics2D)
{
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (Statics.PRESENTATION_CMD_ADD == null && Connection.getInstance().hasConnected())
{
g2.setColor(Color.GREEN);
g2.setFont(font);
g2.drawString("connected", 50, 50);
return;
}
else if (Statics.PRESENTATION_CMD_ADD == null)
{
g2.setColor(Color.GREEN);
g2.setFont(font);
g2.drawString("not connected", 50, 50);
return;
}
String[] content = Statics.PRESENTATION_CMD_ADD.split(Statics.STRING_LIMITER_HASH);
g2.setColor(Color.WHITE);
g2.setFont(font);
for (int i = 0; i < content.length; i++)
{
g2.drawString(content[i], 50, fontSize + fontSize * i + 10);
}
}
}
}
I don't have enough reputation yet to comment, so will need to post as an answer.
I've not even looked at your code but i was having a similar issue when working on the Pi a while back, i was displaying video with image overlays(digital signage). When i went full screen i would get a flicker of the image before the screen would go black and eventually time out and the screen would go to standby.
It turned out to be an issue with the hdmi buffer or something. I never actually solved my issue, i think i just hit the limits of the raspberry pi.
What did work was turning down the resolution. in config.txt on the sd card image i think i changed hdmi mode to 34, this gave me 1920x1280p at 30hz and opposed to 60hz, essentially doubling the buffer. There was a slight loss in quality but barely noticeable.
Sorry i can't be more help, just thought i'd add my 2cents in case it nudges you in the right direction.
Today's question rattling my mind is such. I'm creating a program that allow the user to jump and move left or right, to problem is that whenever I try to jump the program freezes... The idea behind my code is simple, whenever the users presses space(jump) the rectangle "jumps" up and if the y of the rectangle is within a certain height above the obstacle(in this case a rectangle with dimmensions brickx,bricky,brickw, and brickh is the obstacle) then the animation is supposed to stop and the rectangle is supposed to wait for the next command while in place on top of the obstacle. To do this a method stayOnBrick is called during each iteration of the while loop and checks; during the jump, if y is within the needed range, and if y is it then sets the boolean jump = true which should break the loop on the next iteration as well as setting y to the needed value. But when space is pressed, nothing happens, or should I say the program freezes. Thoughts?
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class KeyTest extends Core implements KeyListener{
Window w;
public int x,y;
boolean jump = true;
public int brickx, bricky, brickw, brickh;
public static void main(String args[]){
new KeyTest().run();
}
private String mess = "";
//init also called init from superclass
public void init(){
super.init();
Window w = s.getFullScreenWindow();
w.setFocusTraversalKeysEnabled(false);
w.addKeyListener(this);
y = s.getHeight()-15;
mess = "Press esc to exit";
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
e.consume();
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_ESCAPE){
stop();
}else if(keyCode == KeyEvent.VK_SPACE){
mess = "Pressed: " + KeyEvent.getKeyText(keyCode);
while(y>s.getHeight()-200){
stayOnBrick();
if(jump==false){break;}
else{ try{
y-=20;
w.repaint();
Thread.sleep(40);
}catch(Exception jumpError){
System.out.println("Error in Jumping");
}
}
while(y<s.getHeight()-15){
stayOnBrick();
if(jump==false){
w.repaint();
break;}
else{
try{
y+=20;
Thread.sleep(40);
w.repaint();
}catch(Exception jumpError){
System.out.println("Error in Jumping");
}
}
}
}
}
else if(keyCode == e.VK_RIGHT){
if(x>=s.getWidth()-30){x=s.getWidth()-30;}
x+=20;
w.repaint();
}
else if(keyCode == e.VK_LEFT){
if(x<=0){x=0;}
x-=20;
w.repaint();
}
e.consume();
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
int keyCode = e.getKeyCode();
mess = "Released: " + KeyEvent.getKeyText(keyCode);
jump = true;
e.consume();
}
#Override
public synchronized void draw(Graphics2D g){
brickx=0; bricky=s.getHeight()-100; brickw=300; brickh=20;
Window w = s.getFullScreenWindow();
g.setColor(w.getBackground());
g.fillRect(0, 0, s.getWidth(), s.getHeight());
g.setColor(w.getForeground());
g.fillRect(x, y, 30, 15);
g.drawString(mess, 30, 30);
g.setColor(Color.BLUE);
g.fillRect(brickx, bricky, brickw, brickh);
}
public void stayOnBrick(){
if(y<bricky && y>bricky-30){
y=bricky-15;
jump = false;
}
else{jump = true;}
}
}
whenever I try to jump the program freezes
I'd start by having a look at Concurrency in Swing for the reason for the problem.
I'd suggest having a look at How to use Swing Timers for a possible solution.
I'd also recommend having a look at How to Use Key Bindings to solve the focus related issues with KeyListener
And you might find How to make sprite jump in java? and JApplet creates a ball that bounces and gets progressively less high in Java helpful
This small applet is supposed to move a String from the bottom to the top of applet frame, when it reaches top it should start from the bottom again. Problem is it's only moving when I resize the applet window. It doesn't move itself, why does it works that way?
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class Zad1 extends Applet implements Runnable {
Thread runner;
int yPos = 500;
public void start() {
if (runner == null) {
runner = new Thread(this);
}
}
public void stop() {
if (runner != null) {
runner = null;
}
}
public void run() {
while (true) {
repaint();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void paint(Graphics g) {
g.drawString("Hello java", 50, yPos);
yPos--;
if (yPos < -30)
yPos = 500;
}
}
The thread is not started
runner = new Thread(this);
runner.start(); // <----------- Insert this!
But note that the style of this applet is bad in many ways (e.g. there should be no logic in "paint", you should probably not overwrite "paint" of an Applet at all, you should consider a JApplet, etc...). You should probably read http://docs.oracle.com/javase/tutorial/uiswing/components/applet.html and other examples.
I got a problem I couldn't get to work after about 2 Hours of trying. I want to have a loop that do 2 Methods (Draw and update) but also listen to Mouse/Keyboard events. I have a loop that Draws and Updates, but does nothing outside of the loop ( Listening to events ) I tried alot of things but nothing worked. Help Please?
I tried using the Runnable Thread, using different orders, using wait() and notify(), I've tried alot of things. But basicly I want to know how to run a loop and still check for User Input
Also when I try to quit the program clicking the red "X", it won't quit but still work
Here's the Code:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class main extends Applet implements MouseListener, Runnable {
public main() {
super();
init();
}
Thread t;
Screen screen = new Screen();
String Text = "Hello";
boolean Running = true;
boolean Click = false;
int R = 0x00;
int G = 0x00;
int B = 0x00;
int xpoints[] = {25, 40, 40, 25, 25};
int ypoints[] = {40, 40, 25, 25, 25};
int npoints = 5;
public void run() {
while (Running) {
GameLoop();
}
}
public void init() {
this.addMouseListener(this);
this.setSize(400, 300); //manually set your Frame's size
t = new Thread(this);
t.start();
}
public void paint(Graphics g) {
g.setColor(new Color(R, B, G));
g.fillPolygon(xpoints, ypoints, npoints);
Running = true;
t.run();
}
public void mousePressed(MouseEvent e) { //On Mouse Click
System.exit(0);
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
System.exit(0);
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
public boolean keyDown(Event e, int key) {
return true;
}
public void GameLoop() {
if (Running) {
if (R != 0xff) {
R++;
} else {
if (G != 0xff) {
G++;
} else {
if (B != 0xff) {
B++;
} else {
System.exit(0);
}
}
}
try {
sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
paint(getGraphics());
}
}
public void sleep(int time) throws InterruptedException {
Thread.sleep(time, 0);
}
}
This tutorial should provide some insight as to how your program should be structured. And this one is helpful for the mouse listener.
Issues you should address:
1) You're doing something fishy with the paint method. Why are you calling t.run() in there? The thread t is already running and looping constantly calling the paint() method to redraw the screen. Remove this call and see what you get.
1) The destruction of your thread/applciation is poor. The first example above provides a better way for that to occur
2) You have your System.Exit(0) on mousePressed() with the comment //on mouse click but nothing in mouseClicked()... it works but its bad convention
3)Having your class named main is extremely poor convention that is both confusing and impractical. Rename your class to something like "Game" or similar.
4) Why declare Screen if you don't use it?
I see that you define a Running variable to be true upon initialization. This variable is used to determine whether or not the game should stop. I, however, don't see any place where you modify the value of this variable to false. This would explain why your game never exits.
As for the the game not working, try debugging the application in an IDE. You should then pay attention to what, if any, Exception are being thrown and the values of any variables you are questioning. Hopefully this will give you insight into the behavior of your app.
Don't forget to update us with any new info you discover so we can help you out along the way.
First of all here are some code snippets:
public void startThread() {
this.animationThread = new Thread(this);
this.animationThread.start();
try {
this.animationThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void run() {
pirateMainAnimation.animate();
}
public void animate() {
for (int j = 0; j < 9; j++) {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
break;
}
PirateAnimationPanel.getInstance().setCurrent(j);
PirateAnimationPanel.getInstance().repaint();
}
}
I'm trying to animate some images. The thing is that I want the main thread to wait for the animation thread to finish and then to continue. I searched around, read a little bit and decided to use the join() method. It perfectly waits for the thread to finish but I doesn't animate correctly. The repaint() method gets called 2 times instead of nine. I think maybe the problem is because I used singletons. Here is the singleton implementation.
import java.awt.Graphics;
import java.awt.MediaTracker;
import javax.swing.JPanel;
import uk.ac.aber.dcs.piratehangman.animation.PirateMainAnimation;
import uk.ac.aber.dcs.piratehangman.utilityclasses.AnimationThread;
#SuppressWarnings("serial")
public class PirateAnimationPanel extends JPanel {
private int current;
private MediaTracker mTracker;
private PirateMainAnimation pirateMainAnimation;
private AnimationThread animationThread;
private PirateAnimationPanel() {
this.current = 0;
this.pirateMainAnimation = new PirateMainAnimation();
mTracker = new MediaTracker(this);
this.animationThread = new AnimationThread();
setMediaTracker();
repaint();
}
private void setMediaTracker() {
for (int i = 0; i < 9; i++) {
mTracker.addImage(
this.pirateMainAnimation.getImagesForAnimation()[i],
this.pirateMainAnimation.getImagesForAnimationID()[i]);
try {
mTracker.waitForID(this.pirateMainAnimation
.getImagesForAnimationID()[i]);
} catch (InterruptedException e) {
System.out.println("Error loading image: " + i);
}
}
}
public void playAnimation() {
this.animationThread.startThread();
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
System.out.println("called");
g.drawImage(this.pirateMainAnimation.getImagesForAnimation()[current],
0, 0, this);
}
private static class PirateAnimationPanelHolder {
private static final PirateAnimationPanel pirateAnimationPanel =
new PirateAnimationPanel();
};
public static PirateAnimationPanel getInstance() {
return PirateAnimationPanelHolder.pirateAnimationPanel;
}
public void setCurrent(int current) {
this.current = current;
}
public int getCurrent() {
return current;
}
}
I think you mean that the paintComponent() methods only gets called twice. Also I think you should be able to remove the call to super.paintComponents() if you fill the component to the background color.
The repaint() method only marks the component as dirty and requests a re-render on the next paint.
I would have expected the Swing thread to be able to repaint within the 250ms but I'm not sure what other work is being done/rendered. You might want to put a call to MediaTracker.waitForAll() before the animation.
While the static singleton is not adding much I don't think it is causing a problem (in this case).
Update:
So the problem is that the join() is on the Swing event Thread which is blocking the repainting of the component. I suggested a call like the following to show the "new game dialog after the last animation:
SwingUtilities.invokeLater(new Runnable() {
public void run() { showDialog(); }
})
"Note that events being posted to the EventQueue can be coalesced," which may explain the disparity. Also, be certain to build your GUI on event dispatch thread. See A More Complex Image Icon Example for a more detailed discussion.
Addendum: Improving Perceived Performance When Loading Image Icons has a nice SwingWorker example that may simplify the off-loading.