I am using Intellij to program Java.
I am currently trying to make a top down tile based shooter.
My issue is that my game, after approximately 2 minutes, crashes with a popup saying "Java(TM) Platform SE Binary has stopped working. I recorded the time it took for it to crash 3 times: 1m57s, 1m59s, 1m58s.
The game is in a very simple state right now and I am not sure what could be causing the crash. All of the relevant code is in just two classes: GameFrame.java (extends JFrame) and GamePanel.java (which extends JPanel).
GameFrame.java:
package net.magnusfrater.tds.game;
import javax.swing.*;
public class GameFrame extends JFrame {
public static final int width = 1000;
public static final int height = width / 16 * 10;
private GamePanel gp;
public GameFrame () {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(width,height);
setResizable(false);
setLocationRelativeTo(null);
setTitle("Time Based Fast Paced Top Down Shooter Demo");
gp = new GamePanel();
add(gp);
setVisible(true);
}
public static void main (String[] args) {
GameFrame gf = new GameFrame();
}
}
GamePanel.java
package net.magnusfrater.tds.game;
import net.magnusfrater.tds.input.Keyboard;
import javax.swing.*;
import java.awt.*;
public class GamePanel extends JPanel implements Runnable {
//panel
private Thread thread;
private static boolean running;
private boolean fpsLock;
//input
private Keyboard kb;
//game
private Game game;
public GamePanel () {
//panel
thread = new Thread(this, "Time Based Fast Paced Top Down Shooter Demo");
running = true;
fpsLock = true;
//input
//kb = new Keyboard();
//addKeyListener(kb);
//game
//game = new Game(1);
thread.start();
}
public void run () {
long iTimeNS = System.nanoTime();
int tickRate = 60;
long ns = 1000000000 / tickRate;
int ups = 0;
int fps = 0;
long iTimeS = System.nanoTime();
long s = 1000000000;
while (running) {
long fTimeNS = System.nanoTime();
if (fTimeNS - iTimeNS >= ns){
iTimeNS = System.nanoTime();
tick();
ups++;
if (fpsLock){
repaint();
fps++;
}
}
if (!fpsLock){
repaint();
fps++;
}
long fTimeS = System.nanoTime();
if (fTimeS - iTimeS >= s){
iTimeS = System.nanoTime();
System.out.println("ups: " + ups + "\tfps: " + fps);
ups = 0;
fps = 0;
}
}
System.exit(0);
}
public void tick () {
if (kb != null)
kb.tick();
if (game != null)
game.tick();
}
#Override
public void update (Graphics g) {
paint(g);
}
#Override
public void paint (Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0,0,GameFrame.width, GameFrame.height);
//if (game != null)
//game.paint(g);
}
public static void quitGame () {
running = false;
}
}
I originally thought that the issue was because of the way that I was loading images for spritesheets or maybe the way I was loading text files for the level design but after reworking both of those, the issue remained.
That left me curious and a little bit fed up so I tried finding out more about the explanation for the crash. First I read more from the popup but it didn't say anything useful: (See below)
Second I looked at the exit code given by Intellij: (See below)
I looked up what exit code 255 was but there wasn't anything useful. The best explanation I could find was that exit code 255 meant that the real exit code was out of range: (See below)
I was out of ideas at this point so I just started plain old googling everything I could think of. The problem with googling "Java(TM) Platform SE Binary has stopped working" is that almost every suggested link is a question about Minecraft. Limiting my search to Stack Overflow yielded me some results, but nothing conclusive. Some of the fixes I found were stuff I already tried (such as not handling input streams properly, not handling buffered reader properly, not disposing of elements, etc). I found these links but none of them were truly related to my issue:
(See below)
(See below)
(See below)
(See below)
(See below)
(See below)
The last fix I tried was to re-install Java SE Development Kit 8u101 AND Java SE Development Kit 8u102. I then restarted Intellij. I then restarted my computer.
Nothing worked.
At this point I think I'm just dumb. I've overlooked something easy I can tell. What am I missing?
(ps~ This is a possibly related issue. So if I run my game with almost no content in it with the fps not locked to 60, I get really absurd numbers of frames per second. I didn't think that fps as high as 7,000,000 was possible. I think. I don't know. Have I programmed that wrong as well? Here is a related picture of my ups/fps output: [see below])
(SEE HERE) So Stack Overflow doesn't allow members with a score within a certain threshold post more than 2 links and allows absolutely no posting of images. So here is a link to a google doc with all of the links and images I mentioned above:
https://docs.google.com/document/d/1XrBuVio19GmkFz0EfRzXVp5AJmM5zPfVO6vK3oS3Eaw/edit?usp=sharing
Try and set your -Xmx to something like 2G and see if it runs longer. If so, something is allocating memory and maybe you have that other setting set that exits instead of garbage collecting for some reason.
Also, try changing your code to limit things using Guava's RateLimiter.
…
// class level
final RateLimiter frameLimiter = RateLimiter.create(60.0);
final RateLimiter outputLimiter = RateLimiter.create(1.0);
…
// in run method
while (running) {
frameLimiter.acquire();
repaint();
fps++;
if (outputLimiter.tryAcquire()){
System.out.println("fps: " + fps);
fps = 0;
}
}
I've removed ups and tick(). You should do your work after repainting and I don't think you want to do more work than needed for the next frame, which at the soonest should be at your max rate. Later you'll need to add logic to handle skipping work when frames are being skipped. I might make more sense to increment the fps within repaint.
You could put the output in its own thread and only acquire that limiter if you synchronized the increments and resetting of fps.
Related
I'm currently running into a rather annoying problem.
Im running round about this task, with a Spigot-1.8 in Java 1.8. But this exact code gives me two diffrent Results.
In one the Levelbar of Minecraft just counts down and in another the Levelbar just flickers every time it sets the new XP Value.
private static int buildTask;
private static int buildSeconds = 120;
public static void buildingTime() {
buildTask = Bukkit.getScheduler().scheduleSyncRepeatingTask(Plugin.getInstance(), () -> {
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
onlinePlayer.setLevel(buildSeconds);
}
//executing other Actions with Actionbar and Broadcasting Seconds to all players
if (buildSeconds <= 0) {
//ending here
}
buildSeconds--;
}, 0, 20);
}
I'm using this Spigot: https://getbukkit.org/get/hNiHm0tuqAg1Xg7w7zudk63uHr0xo48D
Already solved.... Let two tasks run at the same time which conflicted
I'm not sure why but when I try to run this the only thing that shows is the last program I ran, I even added the serialVersionUID and it still wont show. Anyone have an i dea on why, maybe some setup problem on my eclipse or coomputer?
import java.awt.Graphics;
import javax.swing.JPanel;
public class Shapes extends JPanel {
private static final long serialVersionUID = 1L;
private int choice;
public Shapes(int userChoice) {
choice = userChoice;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; 1 < 10; i++) {
switch (choice) {
case 1:
g.drawRect(10 + i * 10, 10 + i * 10, 50 + i * 10, 50 + i * 10);
case 2:
g.drawOval(10 + i * 10, 10 + i * 10, 50 + i * 10, 50 + i * 10);
break;
}
}
}
}
First of all, you have no entry-point to your program. You can't just expect a program in Java, or basically any other compiled language to run without an entry point.
Inside your class, you need to have the following for the program to begin:
public static void main(String[] args) {
// Entry-point began. Put code in here.
}
Secondly, it is not a good practise (correct me if I'm wrong) to extend any of the JComponent derivatives. Without explaining again, a good reason can be found here:
Excerpt:
It makes it harder to change things later - if you've made a class public, swapping the superclass is going to break subclasses - it's a choice which, once you've made the code public, you're married to. So if you're not altering the real functionality to your superclass, you get much more freedom to change things later if you use, rather than extend the thing you need. Take, for example, subclassing JPanel - this is usually wrong; and if the subclass is public somewhere, you never get a chance to revisit that decision. If it's accessed as JComponent getThePanel() , you can still do it (hint: expose models for the components within as your API). This especially applies because your class is a Shape. So when Shape extends JPanel, every single shape will.
Object hierarchies don't scale (or making them scale later is much harder than planning ahead) - this is the classic "too many layers" problem. I'll go into this below, and how the AskTheOracle pattern can solve it (though it may offend OOP purists).
Especially since you are extending JPanel, and aren't even initialising a JFrame to begin with. Before starting out with Swing applications in Java, you should read the JavaDoc and Oracles examples beforehand...
JavaDoc: JFrame / JPanel
Example: How to make Frames.
So, revising on what I have said, a basic Swing class would look as follows:
import javax.swing.*;
public class Shapes {
public Shapes() {
JFrame frame = new JFrame();
JPanel window = new JPanel();
frame.setSize(600, 400); // Width: 600, Height: 400.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(window);
window.setLayout(new BorderLayout());
// Perform graphics drawing.
frame.revalidate();
frame.repaint();
}
public static void main(String[] args) {
new Shapes();
}
}
Hello!
I am trying to display a text on the Screen (with Java), but I want it to be delayed, like, every 0.1 seconds, a letter of the text would appear on the screen. It's like Pokemons dialogs. Here's what I am talking about: https://www.youtube.com/watch?v=yUS1IcC5CBY
I don't want the fade and the acceleration of the text, I just want the text to appear letter-by-letter. Also, I would like the text to be a String. Please, can you help me?
Thanks a lot in advance!
You can use two methods:
One is Thread.sleep(), which is shown above:
private static String message = "Your Message";
private static JLable label = new JLabel();
private static String labelMessage = "";
for(int i = 0; i < message.length(); i++){
labelMessage += Character.toString(message.charAt(i));
label.setText(labelMessage);
try{
Thread.sleep(howManyMillisecondsYouShouldWait);//if you want to do it every .1
//seconds, just wait 100 milliseconds.
}catch(InterruptedException e){
Thread.currentThread().interrupt();
}
}
that will forever print it to the screen every 100 milliseconds. However, the only trouble with using Thread.sleep is (and I somehow just learned this the other day, even though I've been programming for a long while) it is not always accurate. It may sleep 100 ms, it may sleep 150, etc. Secondly, a slower computer may take longer to sleep through it.
The other method which you will use more often (probably) is to check the actual time of your system and see if it's been long enough since you last printed it to the screen, like this:
private static long timeOfLastWrite;//at what time did you last update the text?
private static long deltaTimeSinceLastWrite;//how long has it been since you last updated the text?
private static long timeOfFirstWrite;//when did you start?
private static long deltaTimeSinceFirstWrite;//how long has it been since you started?
private static String message = "Your Message";
private static JLabel label = new JLabel();
private static String labelMessage = "";
//print once here:
timeOfFirstWrite = System.currentTimeMillis();
timeOfLastWrite = System.currentTimeMillis();//every time you print to the screen, make
//sure that you make note of it by setting the timeOfLastWrite variable equal to the current time.
labelMessage += Character.toString(message.chatAt(0));
while(!labelMessage.equals(message)){
deltaTimeSinceLastWrite = System.currentTimeMillis() - timeOfLastWrite;
if(deltaTimeSinceLastWrite >= 100){
timeOfLastWrite = System.currentTimeMillis();
deltaTimeSinceFirstWrite = System.currentTimeMillis() - timeOfFirstWrite;
int currentIndexOfChain = (int) deltaTimeSinceFirstWrite / 100;
if(currentIndexOfChain >= message.length()){
currentIndexOfChain = message.length() - 1;
}
labelMessage = message.substring(0, currentIndexOfChain + 1);
label.setText(labelMessage);
}
}
This method isn't even slightly necessary for a program so simple as writing text to the screen 10 times a second. However, it's good to get into the practice of it. You'll learn that if you create a character and tell him to move 10 pixels, Thread.sleep(100), and move again and etc... that on a slower computer, the character will move slower. However, if you tell it to wait until a certain amount of time has passed according to your computer's time, if the user lags out and it takes 200 milliseconds before it tells the character to move again, you can account for that by simply making him move twice as far -- I think it's called framerate independence.
If I did anything wrong with the delta time management please let me now. Again, I just learned about this the other day even though I've been programming for awhile, so don't worry about it too much if you're just now learning to program.
And that's how you make an incredibly long (possibly too long) answer to an incredibly simple question. I hope you benefit from this response.
I'm unable to use Thread.sleep(x) or wait(): java.lang.InterruptedException; must be caught or declared to be thrown
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
You may use this code for doing so. Simply put a thread to print the text onto a jLabel.
new Thread(new Runnable() {
#Override
public void run() {
String x="";
String txt="Hello this is a sample text. Let us see how this works.";
for(int i=0;i<txt.length();i++){
try {
jLabel1.setText(x=x+txt.charAt(i));
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}).start();
How about this?
import javax.swing.Timer;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class DelayText
{
public String example = "As you can see, this sentence is being printed out a character at a time.";
public String transfer = "";
public Timer t;
public int i = 0;
public JFrame f;
public JLabel l;
public DelayText()
{
f = new JFrame("Example");
l = new JLabel();
f.add(l);
f.setSize(450, 200);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
TimerListener tl = new TimerListener();
t = new Timer(100, tl);
t.start();
}
public static void main(String[] args)
{
DelayText d = new DelayText();
}
private class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(i < example.length())
{
transfer += (example.charAt(i));
l.setText(transfer);
i++;
}
if(i >= example.length())
{
t.stop();
}
}
}
}
I am using the timer to create a delay between each character outputted on the JFrame. I noticed a lot of these other ones were a bit more complex, thought this might make things a bit easier to understand.
I Have 1 single java app. ONly Containing 1 JMenu with 48 JMenuItem(s).
Each JMenuItems i set the Icon with Animated GIF.
I have no problem creating it.
And I also have no problem when Running it.
But the problem came, when I running it, and then viewing the JMenuItem.
My GIF(s) Animation seems consuming the PC Process very high!
And the ANimation seems jumping too fast! It's not the usual animation framerate, tough.
So anytime when I run the java app, and then trying the JMenuItem, The CPU Process
is getting higher...!
Look at this Preview: It's taken when My java app runs.
What's the best way to solve this?
What result do you get from this SSCCE? My system peaks to 40 at start-up then jumps to an average of around 20-30. The rendering of the animated GIFs is somewhat jerky.
import java.awt.*;
import javax.swing.*;
class Gif48 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
String url = "http://1point1c.org/gif/thum/plnttm.gif";
int w = 12;
int h = 4;
JPanel p = new JPanel(new GridLayout(h,w,2,2));
String pre = "<html><body><img src='";
String post = "'>";
for (int ii=0; ii<w*h; ii++) {
JLabel l = new JLabel(
pre + url + post );
l.setBackground(Color.BLACK);
l.setOpaque(true);
p.add(l);
}
JOptionPane.showMessageDialog(null, p);
}
});
}
}
What's the best way to solve this?
Don't use animated GIFs in the controls of GUIs.
I have found the solutions guys! The GIF Animation has lots of frames. In each frames they have their own timing. When I reopened one single GIF Animation File, I could see clearly that the 0-time framerate is the problem. Now I should Changed it to somewhat above 0.1 framerate, that's all problem solved.
I'm looking for a method of counting Frames Per Second in game applications, the problem is that i dont have the source code for any of those apps, they dont have such functionality implemented inside. To be honest i dont really expect this to be possible but it was worth to ask.
And to be perfectly clear i understand that i need a basic knowledge and code of the main painting loop to count FPS.
Best Regards
What is the problem of making FPS counting when you have a main paint loop (don't you?).
I'm not familiar with Android features, but I'm sure it is done there the same in any game on any OS. The easiest way to make a game - is to make 2 threads. First one will be for logic actions (calculating trajectories, object position change over time, etc.). Second thread will take current game state (calculated by first thread) and draw it on the screen.
Here is the commented code on both threads with FPS counter:
//Class that contain current game state
class GameState {
private Point objectPosition;
public Point getObjectPosition() {
return objectPosition;
}
public void setObjectPosition(Point pos) {
this.objectPosition = pos;
}
}
//Runnable for thread that will calculate changes in game state
class GameLogics implements Runnable {
private GameState gameState; //State of the game
public GameLogics(GameState gameState) {
this.gameState = gameState;
}
public void run() {
//Main thread loop
while (true) { //Some exit check code should be here
synchronize (gameState) {
gameState.setObjectPosition(gameState.getObjectPosition()+1); //Move object by 1 unit
}
Thread.sleep(1000); //Wait 1 second until next movement
}
}
}
//Runnable for thread that will draw the game state on the screen
class GamePainter implements Runnable {
private Canvas canvas; //Some kind of canvas to draw object on
private GameState gameState; //State of the game
public GamePainter(Canvas canvas, GameState gameState) {
this.canvas = canvas;
this.gameState = gameState;
}
public void drawStateOnCanvas() {
//Some code that is rendering the gameState on canvas
canvas.drawLine(...);
canvas.drawOtherLine(...);
....
}
public void run() {
//Last time we updated our FPS
long lastFpsTime = 0;
//How many frames were in last FPS update
int frameCounter = 0;
//Main thread loop
//Main thread loop
while (true) { //Some exit check code should be here
synchronize (gameState) {
//Draw the state on the canvas
drawStateOnCanvas();
}
//Increment frame counter
frameCounter++;
int delay = (int)(System.getCurrentTimeMillis() - lastFpsTime);
//If last FPS was calculated more than 1 second ago
if (delay > 1000) {
//Calculate FPS
double FPS = (((double)frameCounter)/delay)*1000; //delay is in milliseconds, that's why *1000
frameCounter = 0; //Reset frame counter
lastFpsTime = System.getCurrentTimeMillis(); //Reset fps timer
log.debug("FPS: "+FPS);
}
}
}
}
I'm not too knowledgeable with Android Game development, but in Java2D (it's a bit hacky but it works...) I would xboot a jar with the edited JRE class which controls the rendering (eg Canvas) into the process.
This is a good read on game loop. It explains the various implementations and pros/cons of game loops.
And this is a good tutorial on implementing the gameloop + FPS counter in Android.