Full Screen game window wont display correctly - java

Hello i am trying to Create the beginning of a full screen game and i am having issues. I want a blue background with white text and the entire screen to be changed to 800*600. The problem is i get a screen with an 800*600 box in the middle(not visible but i can tell by mouse boundaries) and my background is black.
My Code:
import java.awt.*;
import javax.swing.JFrame;
/**
* Write a description of class Full here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class Full extends JFrame
{
public static void main(String[] args){
DisplayMode dm = new DisplayMode(800,600,16, DisplayMode.REFRESH_RATE_UNKNOWN);
Full full = new Full();
full.run(dm);
}
public void run(DisplayMode dm){
setBackground(Color.BLUE);
setForeground(Color.WHITE);
setFont(new Font("Arial", Font.PLAIN,24));
Screen s = new Screen();
try{
s.setFullScreen(dm,this);
try{
Thread.sleep(15000);
}catch(Exception ex){}
}finally{
s.restoreScreen();
}
}
public void paint(Graphics g){
if(g instanceof Graphics2D){
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
g.drawString("This is gonna be awesome!!",200,200);
}
}
public class Screen
{
private GraphicsDevice vc;
Window myWindow;
public Screen(){
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
vc = env.getDefaultScreenDevice();
}
public void setFullScreen(DisplayMode dm, JFrame myWindow){
myWindow.setUndecorated(true);
myWindow.setResizable(false);
vc.setFullScreenWindow(myWindow);
if(dm != null && vc.isDisplayChangeSupported()){
try{
vc.setDisplayMode(dm);
}catch(Exception ex){}
}
}
public Window getFullScreenWindow(){
return vc.getFullScreenWindow();
}
public void restoreScreen(){
Window w = vc.getFullScreenWindow();
if(w != null){
w.dispose();
}
vc.setFullScreenWindow(null);
}
}

This is a short answer, because it seems that you are on the wrong trace :)
Games should be using OpenGL or DirectX, so the graphical work is done by the GPU. I strongly recommend OpenGL, since it is compatible with every platform. The way you started, the game will run completely on the CPU, which is not good.
Take a look at LWJGL (LightWeight Java Game Library). It is a cross-platform library that allows you to use OpenGL. It will require some Googling for tutorials, but it is really worth it. Your performance of the game will be a lot better, and your game will be made the way it has to be. Just to give you an idea, Minecraft is made with LWJGL.
OpenGL allows you to make a quick start with your game development, using some simple methods, which is good first a first game experience. Later on, you will find out how to do things more efficient, but that would be too much information to start of with :D
Good luck!

Related

Screen objects sometimes not rendering

I am a mildly experienced programmer who has created several game engine templates and small 2d games in Java. I am currently expanding to 3d game engines and am re-writing a previous engine to be more adaptive and Object-oriented.
My issue is, and has been periodically, that the objects are only sometimes rendered. This causes me to have to constantly re-run the program just to display any images.
I have not found any direct answers to this question, and nobody else seems to have this same issue (even when observing sources with the exact same code setup). The problem apparently lies within the render() method sometimes not properly creating or utilizing the Graphics & BufferStrategy objects while inside a thread called from the main method.
Here is some code of the 'Main' class:
public Main() {
addScreenAndFrame();
}
public static void main(String[] args) {
main = new Main();
frame.add(main);
thread = new Thread(main);
running = true;
thread.start();
}
public void run() {
while (running) {
render();
tick();
}
}
public void tick() {
screen.tick();
}
public void render() {
bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
screen.paintComponent(g);
g.dispose();
bs.show();
}
Here is some code from the Screen class:
public Screen(int width, int height) {
this.width = width;
this.height = height;
addEntities();
}
public void paintComponent(Graphics g) {
p.render(g);
}
public void tick() {
KeyInput.tick();
renderInput();
}
public void addEntities() {
p = new PolygonObject(new double[] {50,200,50}, new double[] {50,200, 200} );
}
And finally here is the PolygonObject class:
public PolygonObject(double x[], double y[]) {
Screen.polygonSize ++;
polygon = new Polygon();
for (int i=0; i < x.length; i++) {
polygon.addPoint((int)x[i], (int)y[i]);
}
}
public void render(Graphics g) {
g.fillPolygon(polygon);
g.setColor(Color.black);
g.drawPolygon(polygon);
}
I don't know why calling render() while within a thread would yield inconsistent results when drawing images to the screen. I have seen many source codes for game templates and tutorials with the exact same code without any rendering issues. The only way rendering works consistently is when I draw images with the paintComponent() method of the Canvas class outside of a thread which limits my program functionality and is poor design of a game engine.
I would like an explanation of this and any possible solutions. There is NO accurate way for me to build the game engine without the use of a thread in order to have controlled time-based functionality.
The run() method called by the 3rd thread was unstable and sometimes did not properly construct each object due to encapsulation issues.
I have removed the extra thread and have re-structured the engine to do all rendering within the JPanel's paintComponent() method in the Screen class. The Main class has been re-structured to only create the frame then add the Screen and KeyInput objects to the frame while managing the game logic and input.
The engine now renders with 100% success and all objects work as they should.
SOLVED 11/17/2017

Can Java have text in the background of a graphics file?

I have this code and its supposed to have the text "Simple Animation" scroll across the screen in swirling colors. Right now, it does that, but even after the text moves along, the color still stays. I was wondering if there was a way to have text in the background. For example, I was thinking I could just print out the exact same "Simple Animation" but in the same color as the background and about 10 pixels behind the actual text. However, when I tried this, the white text (that's the background color) just covered the swirling colors. I tried googling if I could have background text, but from I read, the only thing that a background can do is set the color. So, is there a way to have text in the background in a Java Graphics file?
Here is my Code:
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Font;
import javax.swing.*;
public class Scrolling_Sign extends JApplet implements Runnable {
String mesag = "Simple Animation";
Font f = new Font("Bauhaus 93",Font.BOLD,72);
Color colors[] = new Color[100000];
Thread runThread;
int Xposition = 600;
public void init() {
setBackground(Color.white);
}
public void start() {
if (runThread == null) {
runThread = new Thread(this);
runThread.start();
}
}
public void stop() {
if (runThread != null) {
runThread.stop();
runThread = null;
}
}
public void run() {
float c = 0;
for (int i = 0; i < colors.length; i++) {
colors[i] = Color.getHSBColor(c, (float)1.0,(float)1.0);
c += .02;
}
int i = 0;
while (true) {
setForeground(colors[i]);
repaint();
i++;
try { Thread.sleep(100); }
catch (InterruptedException e) { }
if (i == colors.length ) i = 0;
}
}
public void paint(Graphics g) {
g.setFont(f);
g.drawString(mesag,Xposition,100);
Xposition--;
if (Xposition < -290) {
Xposition = 600;
}
}
}
Thank you!
Suggestions:
Never draw directly within a JApplet or other top-level window.
Instead draw in the paintComponent of a JPanel that is displayed within the applet. The Swing tutorials will show you how.
Be sure to call the super.paintComponent(g) method within your override, and again read the Swing tutorials to see why. For more tutorials see: Swing Info
This is Swing -- use a Swing Timer to drive your animation, not threads.
If you ever do use Threads, never call Thread#stop() or use any other deprecated methods. Please read Why is Thread.stop deprecated?.
Please look at this answer for an example of Swing animation using a Swing Timer.
Unless this is for a class assignment, don't create JApplets as this is a dead technology, something even Oracle will tell you.
To display text in the background use the java.awt.Graphics method for writing text: drawString(...). Either that or place a JLabel over your background image.

Flickering white on canvas

I figured out a solution minutes after posting, but due to low reputation I couldn't delete the post
For the fun of it I decided to start working on something which might turn into a game at some point.
I'm trying to draw some circles and move them in a given direction currently. This causes flickering. It's very likely that I oversee something very basic but I can't figure out why it doesn't render smoothly.
My board class looks something like (removed what I deemed unnecessary):
public class Board extends Canvas implements Runnable {
public static void main(String[] args) {
Board board = new Board();
board.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
JFrame frame = new JFrame("Circles");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(board);
frame.pack();
frame.setVisible(true);
board.start();
}
#Override
public void run() {
while (running) {
process();
repaint();
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
The paint method:
public void paint(Graphics g1) {
super.paint(g1);
Graphics2D g = (Graphics2D) g1;
for (Ball ball : Ball.BALLS) {
g.drawOval((int) ball.getLocation().getX(), (int) ball.getLocation().getY(), ball.getRadius(), ball.getRadius());
}
}
My process method:
private void process() {
if (utilities.randInt(1, 100) < 10 && Ball.getBallCount() < 40) {
Ball.spawnNew(this);
}
for (Ball ball : Ball.BALLS) {
ball.move(this);
}
Ball.BALLS.removeAll(Ball.TO_REMOVE);
Ball.TO_REMOVE.clear();
}
The move method basically increments the x-value of the ball by a given value each time its called (moving it right).
Like I said, I'm unsure why it flickers so if you have any pointers please do tell.
Thanks!
This sounds like a case where you need to perform double-buffering, so that one copy of your canvas can remain shown while you are updating the other.
You're using AWT here, and I don't know how to implement double-buffering manually with AWT. However, if you're willing to use Swing here you can take advantage of automatic double-buffering. See the question about How to make canvas with Swing? as well as Oracle Technology Network's article on Painting in AWT and Swing.
The basic idea would be:
extend javax.swing.JPanel instead of Canvas (which means when you override paint(Graphics) you're now overriding it from javax.swing.JComponent instead of java.awt.Component)
create a constructor with super(true) to enable double-buffering.
Edit: Also, as iccthedral points out, you're better off overriding paintComponent(Graphics) and including a call to super.paintComponent(Graphics). See Difference between paint, paintComponent and paintComponents in Swing.
You need double buffering. To do this you need to create a BufferedImage and get the Graphics from it. Paint everything to the image, render the image on to the screen, then finally fill the image with a the background color or image to reset it.
Sample:
//one time instantiation
BufferedImage b = new BufferedImage(width, height, mode);
In paint(Graphics g):
Graphics buffer = b.getGraphics();
//render all of the stuff on to buffer
Graphics2D g = (Graphics2D) buffer;
for (Ball ball : Ball.BALLS) {
g.drawOval((int) ball.getLocation().getX(), (int) ball.getLocation().getY(), ball.getRadius(), ball.getRadius());
}
g1.drawImage(b, 0, 0, width, height, null);
g.setColor(Color.BLACK);
//reset the image
g.drawRect(0, 0, width, height);
g.dispose();

Java animation stutters when not moving mouse cursor

I have a quite simple animation, a text in a big font moving continuously (pixel by pixel) to the left. The text is first converted to an image, then a timer task is started which repeatedly (every 10-20 ms) decrements the x coordinate of the image by 1, and does a repaint().
This program shows a strange behavior on some systems. On my PC with a nVidia card it runs smoothly. On my Vaio notebook, on a BeagleBoneBlack and on a friend's Mac it stutters heavily. It appears to pause for a while, then jump to the left about 10 pixels, pause again and so on.
What stumps me is the fact that on these systems the animation only stutters if you don't touch the mouse. As long as you move the mouse cursor within the window, no matter how slowly, or drag the window itself around, the animation runs perfectly smooth!
Can anybody explain this? Here is the program:
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.*;
class Textimg extends JComponent
{
String str;
Font font;
int x = 0;
final int ytext = 136;
Image img;
public Textimg(String s)
{
str = s;
font = new Font("Noserif", Font.PLAIN, 96);
setLayout(null);
}
protected void paintComponent(Graphics g)
{
if (img == null)
{
img = createImage(4800, 272);
Graphics gr = img.getGraphics();
gr.setFont(font);
gr.setColor(Color.BLACK);
gr.fillRect(0, 0, 4800, 272);
gr.setColor(new Color(135, 175, 0));
gr.drawString(str, 0, ytext);
gr.dispose();
}
g.drawImage(img, x, 0, this);
}
public void addX(int dif)
{
if (isVisible())
{
x = x + dif;
Graphics g = getGraphics();
if (g != null) paintComponent(g);
}
}
}
public class Banner extends JFrame
{
StringBuffer buf;
int sleeptime = 10;
Banner(String path) throws IOException
{
setSize(new Dimension(480, 272));
setTitle("Java Test");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(null);
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(path), "UTF-8"));
buf = new StringBuffer();
while (true)
{
String line = reader.readLine();
if (line == null) break;
buf.append(line);
}
final Textimg textimg = new Textimg(buf.toString());
add(textimg);
textimg.setBounds(0, 0, 480, 272);
final javax.swing.Timer timer = new javax.swing.Timer(200, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
textimg.addX(-1);
}
});
timer.setDelay(sleeptime);
timer.start();
}
//----------------------------------------------------------------------
public static void main(String[] args) throws Exception
{
new Banner(args[0]).setVisible(true);
}
}
Try calling this method when you are done drawing:
Toolkit.getDefaultToolkit().sync();
This flushs the graphics buffer which some systems like Linux use. See the Javadoc: http://docs.oracle.com/javase/7/docs/api/java/awt/Toolkit.html#sync()
Don't, EVER, use getGraphics and you should NEVER call paintComponent yourself, this not how custom painting is done in Swing. Instead, update the state and call repaint.
Don't rely on magic numbers, use the information you have at hand (getWidth and getHeight)
Swing components are doubled buffered, so it's unlikely you would need to create you own buffered strategy. This simple act could be slowing down your painting
You must call super.paintComponent. This is even more important with JComponent, as it is not opaque and failing to do so could result in some nasty paint artefacts.
You should override JComponent#getPreferredSize so it can work with layout managers for efficiently.
You may find a shorter delay produces a better illusion, say 40 milliseconds (roughly 25fps) for example
Take a look at Swing animation running extremely slow, which through some object management and optimisation, was able to increase from 500 animated objects up to 4500.
Also take a look at Performing Custom Painting and Painting in AWT and Swing in particular
Profiling shows that you are saturating the shared thread used by javax.swing.Timer. One mitigation strategy is to use a longer period and/or a larger increment/decrement, as shown here.
Addendum: In addition, you are laboriously re-rendering the entire image in each call to paintComponent(). Instead, render it once using TextLayout, seen here, and draw() only the newly visible portion each time.
Problem solved!
To answer my own question: After realizing that any continuous input (mouse or keyboard) makes the animation run smoothly, I remembered that inputs can be generated by the program itself, using an object of the class java.awt.Robot. That lead to a simple workaround:
Create a Robot and let it press a key or a mouse move in each animation cycle.
final Robot robot = new Robot();
javax.swing.Timer timer = new javax.swing.Timer(initialDelay, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
// update your image...
robot.keyPress(62);
}
});
This is a kludge, but works perfectly.

How to get rid of the flicker that appears during my animation?

I'm learning Java by making a small game in a JApplet.
I got a little problem with my sprite's animation.
Here is the code :
this.sprite.setBounds(0,0,20,17);
this.sprite.setIcon(this.rangerDown);
for(int i = 0; i< 16;i++)
{
this.sprite.setBounds(this.sprite.getX(), this.sprite.getY()+1, 20, 17);
this.sprite.update(this.sprite.getGraphics());
try{
Thread.currentThread().sleep(100);
}catch(InterruptedException e){
}
}
It left some flicker during the animation. Once the animation end, the flicker disappears, but it's kind of ugly... I guess there is some step I missed.
I use this method because it gives the better result for now, but I would like to stay without AWT if possible, using Swing instead.
Any ideas how to get rid of the flicker?
Thanks for reading.
Screenshoot (Can't post images, sorry).
This is not a shadow. Its the border of your sprite. It just happens to be black and appears as a shadow. If you change the amount you shift your sprite (lets say by 50 pixels, not just 1) you will see what i mean.
To fix it what you need to do is to draw the background as well each time you update the location of your sprite. Although this will probably produce flickering.
The correct way to do it is to change the way you draw your objects. You need to override the paintComponent method of your panel and then simply call repaint each time you have updated the locations of your sprites.
EDIT:
See this code sample for basic usage. NOTE: This is NOT how you should write animation using Threads. I wrote that to show you what goes in the paintComponent method and wrote the animation Thread to show you that the "shadow" you mentioned is gone. NEVER have a non ending run loop in a thread :)
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
JFrame f = new JFrame("Test");
MyPanel c = new MyPanel();
f.getContentPane().add(c);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(350, 100);
f.setVisible(true);
}
}
class MyPanel extends JPanel {
int x = 0;
boolean toTheRight = true;
public MyPanel() {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
x = (toTheRight)?x+5:x-5;
if (x>300)
toTheRight = false;
if (x<0)
toTheRight = true;
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g.create();
g2.setPaint(Color.white);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setPaint(Color.red);
g2.fillOval(x-2, 50, 4, 4);
}
}
The problem is double buffering.
In Applets:
Double buffering is done almost automatically. Call repaint() instead of paint in your method.
In Swing, there are many ways to do it. I usually go for the BufferStrategy route. When you're initializing your frame, do this:
JFrame frame;
... code to init frame here
frame.createBufferStrategy(2);
Then in your draw methods:
Graphics g = getBufferStrategy().getDrawGraphics();
..code to do drawing here...
g.dispose();
getBufferStrategy().show();

Categories