This is my ScreenManager class which is used for getting the perfect DisplayMode & setting the screen to fullscreen
import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
public class ScreenManager
{
private GraphicsDevice vc;
//give vc access to monitor screen
public ScreenManager()
{
GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
vc = e.getDefaultScreenDevice();
}
//get all compatible DM
public DisplayMode[] getCompatibleDisplayModes()
{
return vc.getDisplayModes();
}
//compares DM passed into vc DM & see if they match
public DisplayMode findFirstCompatibleMode(DisplayMode modes[])
{
DisplayMode goodModes[] = vc.getDisplayModes();
for ( int x = 0; x < modes.length; x++)
{
for( int y = 0; y < goodModes.length; y++)
{
if(displayModesMatch(modes[x], goodModes[y]))
{
return modes[x];
}
}
}
return null;
}
//get current DM
public DisplayMode getCurrentDisplayMode()
{
return vc.getDisplayMode();
}
//checks if two modes match each other
public boolean displayModesMatch(DisplayMode m1, DisplayMode m2)
{
if(m1.getWidth() != m2.getWidth() || m1.getHeight() != m2.getHeight())
{
return false;
}
if(m1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m1.getBitDepth() != m2.getBitDepth())
{
return false;
}
if(m1.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m2.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m1.getRefreshRate() != m2.getRefreshRate())
{
return false;
}
return true;
}
//make frame full screen
public void setFullScreen(DisplayMode dm)
{
JFrame f = new JFrame();
f.setUndecorated(true);
f.setIgnoreRepaint(true);
f.setResizable(true);
vc.setFullScreenWindow(f);
if( dm != null & vc.isDisplayChangeSupported())
{
try
{
vc.setDisplayMode(dm);
}
catch(Exception ex) { }
}
f.createBufferStrategy(2);
}
//we will set graphics object to this
public Graphics2D getGraphics()
{
Window w = vc.getFullScreenWindow();
if(w != null)
{
BufferStrategy s = w.getBufferStrategy();
return (Graphics2D)s.getDrawGraphics();
}
else
{
return null;
}
}
//update displaye
public void update()
{
Window w = vc.getFullScreenWindow();
if( w != null )
{
BufferStrategy s = w.getBufferStrategy();
if(!s.contentsLost())
{
s.show();
}
}
}
//return full screen window
public Window getFullScreenWindow()
{
return vc.getFullScreenWindow();
}
//get width of window
public int getWidth()
{
Window w = vc.getFullScreenWindow();
if( w != null)
{
return w.getWidth();
}
else
{
return 0;
}
}
//get height of window
public int getHeight()
{
Window w = vc.getFullScreenWindow();
if( w != null)
{
return w.getHeight();
}
else
{
return 0;
}
}
//get out of full screen
public void restoreScreen()
{
Window w =vc.getFullScreenWindow();
if( w != null)
{
w.dispose();
}
vc.setFullScreenWindow(null);
}
//create image compatible with your moitor
public BufferedImage createCompatibleImage(int w, int h, int t)
{
Window win = vc.getFullScreenWindow();
if( win != null)
{
GraphicsConfiguration gc = win.getGraphicsConfiguration();
return gc.createCompatibleImage(w, h, t);
}
else
{
return null;
}
}
}
This is the Core class which I used for initializing the screen, looping mechanism, etc.
import java.awt.*;
import javax.swing.*;
public abstract class Core
{
private static DisplayMode modes[] = {
new DisplayMode(800, 600, 32, 0),
new DisplayMode(800, 600, 24, 0),
new DisplayMode(800, 600, 16, 0),
new DisplayMode(640, 480, 32, 0),
new DisplayMode(640, 480, 24, 0),
new DisplayMode(640, 480, 16, 0),
};
private boolean running;
protected ScreenManager s;
//stop method
public void stop()
{
running = false;
}
//call inint & gameloop
public void run()
{
try
{
init();
gameloop();
}
finally
{
s.restoreScreen();
}
}
//set to full screen
public void init()
{
s = new ScreenManager();
DisplayMode dm = s.findFirstCompatibleMode(modes);
s.setFullScreen(dm);
Window w = s.getFullScreenWindow();
w.setFont(new Font("Arial", Font.PLAIN, 20));
w.setBackground(Color.GREEN);
w.setForeground(Color.WHITE);
running = true;
}
//main gameloop
public void gameloop()
{
long startTime = System.currentTimeMillis();
long cumTime = startTime;
while(running)
{
long timePassed = System.currentTimeMillis() - cumTime;
cumTime += timePassed;
update(timePassed);
Graphics2D g = s.getGraphics();
draw(g);
g.dispose();
s.update();
try
{
Thread.sleep(20);
}
catch(Exception ex) { }
}
}
//update animation
public void update(long timePassed) { }
//draws to the screen
public abstract void draw(Graphics2D g);
}
This is the actual Game class which I used for designing starting screen on window
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Game extends Core implements KeyListener, MouseListener
{
public static void main(String []args)
{
new Game().run();
}
private String mess = "";
private Image VRacer;
private String start = "Start", controls = "Controls", credits = "Credits", exit = "Exit";
private void loadPics()
{
VRacer = new ImageIcon("VRacers.png").getImage();
}
public void init()
{
super.init();
loadPics();
Window w = s.getFullScreenWindow();
w.setFocusTraversalKeysEnabled(false);
w.addKeyListener(this);
w.addMouseListener(this);
mess = "Press Esc to Close Application";
}
//draw
public synchronized void draw(Graphics2D g)
{
Window w = s.getFullScreenWindow();
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setColor(Color.BLACK);
g.fillRect(0, 0, s.getWidth(), s.getHeight());
g.setColor(Color.YELLOW);
g2.drawString(mess, 30, 30);
g.drawImage(VRacer, 160, 50, null);
g2.drawString(start, 355, 200);
g2.drawString(controls, 340, 270);
g2.drawString(credits, 345, 340);
g2.drawString(exit, 360, 410);
}
//key pressed
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_ESCAPE)
{
stop();
}
else
{
mess = "Pressed : " + KeyEvent.getKeyText(keyCode);
e.consume();
}
}
//key pressed
public void keyTyped(KeyEvent e)
{
e.consume();
}
//key released
public void keyReleased(KeyEvent e)
{
int keyCode = e.getKeyCode();
mess = "Released : " + KeyEvent.getKeyText(keyCode);
e.consume();
}
//Mouse pressed
public void mousePressed(MouseEvent e)
{
if( (e.getX() >= 355 && e.getX() <= 396) && (e.getY() >= 174 && e.getY() <= 200) )
{
mess = "Pressed : " + start + " & location : (" + e.getX() + ", " + e.getY() + ")";
}
if( (e.getX() >= 340 && e.getX() <= 410) && (e.getY() >= 244 && e.getY() <= 270) )
{
mess = "Pressed : " + controls + " & location : (" + e.getX() + ", " + e.getY() + ")";
}
if( (e.getX() >= 345 && e.getX() <= 407) && (e.getY() >= 314 && e.getY() <= 340) )
{
mess = "Pressed : " + credits + " & location : (" + e.getX() + ", " + e.getY() + ")";
}
if( (e.getX() >= 360 && e.getX() <= 390) && (e.getY() >= 384 && e.getY() <= 410) )
{
stop();
mess = "Pressed : " + exit + " & location : (" + e.getX() + ", " + e.getY() + ")";
}
}
//Mouse released
public void mouseReleased(MouseEvent e) { }
//Mouse clicked
public void mouseClicked(MouseEvent e) { }
//Mouse entered
public void mouseEntered(MouseEvent e) { }
//Mouse exited
public void mouseExited(MouseEvent e) { }
//
}
I have added some text on the screen & when mouse clicked in the region bounded by the text it gives the output.
But how can I clear the screen if I want to draw something new on the screen when I click Start, Controls, or Credits???
Such as remove everything like Start, Credits, Controls, Exit & the Image
So I can draw something new on that blank screen.
thnx for help in advance...
Related
i have a problem with the DS Desktop Notify library
in this library, all of notify banners has left to right orientation
i want to change the direction of these notifies from LTR to RTL
(the icons most be in the right side of the banner, also title and message need to start from right side of the banner
how can i do this in this library?
https://i.imgur.com/uTlOpqs.png "screenshot"
i have tried using the "applyComponentOrientation" for the frame, but it's not working
private static class DesktopLayoutFrame extends JDialog {
Image bg;
boolean nativeTrans;
boolean finished=true;
boolean clicked=false;
public DesktopLayoutFrame() {
super((JFrame)null,"DesktopLayoutFrame");
setUndecorated(true);
nativeTrans=Utils.isTranslucencySupported();
setBackground(new Color(0,0,0,nativeTrans? 0:255));
setContentPane(new JComponent(){
#Override
public void paintComponent(Graphics g){
render((Graphics2D)g);
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent evt){
clicked=true;
}
});
setFocusableWindowState(false);
setAlwaysOnTop(true);
System.out.println("Desktop Notify Frame deployed.");
}
#Override
public void setVisible(boolean visible) {
boolean bool=isVisible();
if (visible) {
Rectangle screenSize = Utils.getScreenSize();
setBounds(screenSize.x+screenSize.width-310, screenSize.y,
305, screenSize.height-5);
if (!bool && !nativeTrans)
bg=Utils.getBackgroundCap(getBounds());
}
super.setVisible(visible);
}
/**
* Paints the window contents.
* #param rd a graphics2D object received from the original paint event.
*/
public void render(Graphics2D rd) {
Point p = getMousePosition();
finished = false;
int x = 0, y = getHeight();
long l = System.currentTimeMillis();
if (windows.isEmpty()) finished = true;
int cur = Cursor.DEFAULT_CURSOR;
if (!nativeTrans) rd.drawImage(bg, 0, 0, this);
for (int i = 0; i < windows.size(); i++) {
DesktopNotify window = windows.get(i);
if (window.isVisible()) {
y -= window.h;
if (window.popupStart == 0) {
window.popupStart = System.currentTimeMillis();
}
if (y > 0) {
boolean hover = false;
if (p != null) {
if (p.y > y && p.y < y + window.h) {
hover = true;
if (window.getAction() != null) {
cur = Cursor.HAND_CURSOR;
}
if (clicked) {
if (window.getAction() != null) {
final DesktopNotify w = window;
final long lf = l;
java.awt.EventQueue.invokeLater(new Runnable(){#Override public void run(){
w.getAction().actionPerformed(new ActionEvent(w, ActionEvent.ACTION_PERFORMED, "fireAction", lf, 0));
}});
}
if (window.expTime() == Long.MAX_VALUE) {
window.timeOut = l - window.popupStart + 500;
}
}
}
}
window.render(x, y, hover, rd, l);
if (window.markedForHide) {
window.timeOut = l - window.popupStart + 500;
window.markedForHide = false;
}
} else {
window.popupStart = l;
}
if (l > window.expTime() || (y <= 0 && window.markedForHide)) {
window.markedForHide = false;
window.setVisible(false);
windows.remove(window);
i--;
}
y -= 5;
}
}
clicked = false;
setCursor(new Cursor(cur));
}
}
i think above code in "DesktopNotifyDriver.java" has to be edited for this. sorry for my english
Please Help Me Through This
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
How can I make my applet so it goes to a start page and then to the game? So there is a Start Button, a Exit Button, and when I click the Start only then the game starts. Please answer in simple terms if possible since I am a beginner. Thanks :)
Main.java
import java.awt.Graphics;
public class Main extends GameLoop {
/**
*
*/
private static final long serialVersionUID = 1L;
public void init(){
setSize(960,540);
Thread th = new Thread(this);
th.start();
offscreen = createImage(960,540);
c = offscreen.getGraphics();
addKeyListener(this);
}
public void paint(Graphics g)
{
c.clearRect(0,0,960,480);
c.drawImage(background, 0, 0, this);
c.drawImage(mario, x, y, 100, 100, this);
c.drawImage(goomba, ax, ay, 30, 30, this);
c.drawImage(foreground, 0, 0 , this );
c.drawImage(pipes, 0, 0, this);
c.drawImage(block1, 0, 0, this);
c.drawImage(block2, 0, 0, this);
c.drawImage(block3, 0, 0, this);
c.drawImage(block4, 0, 0, this);
c.drawImage(block5, 0, 0, this);
c.drawImage(block6, 0, 0, this);
c.drawImage(block7 , 0, 0, this);
//c.drawImage(blocks, 0, 0, this);
g.drawImage(offscreen, 0 , 0 ,this);
}
#Override
public void update(Graphics g){
paint(g);
}
}
GameLoop.java
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class GameLoop extends Applet implements Runnable, KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;
public int x,y,ax,ay;
public Image offscreen;
public Graphics c;
public boolean jump,down,right,left;
public BufferedImage background, foreground, pipes, blocks, block1, block2, block3, block4, block5, block6, block7, walk2, walk3, walk4, walk5, walk6, jumpR,jumpL, mario, goomba, deadMario, money, block;
public BufferedImage Bblock1, Bblock2, Bblock3;
public int wow;
public int wow2;
public double counter = 4;
public int MaxH, MidH, MinH, delta;
#Override
public void run() {
x = 60;
y = 440;
ax = x +5;
ay = 493;
MinH = 440;
try {
background = ImageIO.read(new File("resources/background1.png"));
foreground = ImageIO.read(new File("resources/foreground1.png"));
blocks = ImageIO.read(new File("resources/blocks1.png"));
pipes = ImageIO.read(new File("resources/pipes1.png"));
walk2 = ImageIO.read(new File("resources/walk2.png"));
walk3 = ImageIO.read(new File("resources/walk3.png"));
walk4 = ImageIO.read(new File("resources/walk4.png"));
walk5 = ImageIO.read(new File("resources/walk5.png"));
walk6 = ImageIO.read(new File("resources/walk6.png"));
jumpR = ImageIO.read(new File("resources/jumpR.png"));
jumpL = ImageIO.read(new File("resources/jumpL.png"));
goomba = ImageIO.read(new File("resources/goomba.gif"));
deadMario = ImageIO.read(new File("resources/deadmario.png"));
money = ImageIO.read(new File("resources/money.png"));
block = ImageIO.read(new File("resources/Block.png"));
block1 = ImageIO.read(new File("resources/block1.png"));
block2 = ImageIO.read(new File("resources/block2.png"));
block3 = ImageIO.read(new File("resources/block3.png"));
block4 = ImageIO.read(new File("resources/block4.png"));
block5 = ImageIO.read(new File("resources/block5.png"));
block6 = ImageIO.read(new File("resources/blocks6.png"));
block7 = ImageIO.read(new File("resources/block7.png"));
Bblock1 = ImageIO.read(new File("resources/Bblock1.png"));
Bblock2 = ImageIO.read(new File("resources/Bblock2.png"));
Bblock3 = ImageIO.read(new File("resources/Bblock3.png"));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
mario = walk2;
while(true)
{
if (y <=440&& jump != true){
y += 5;
}
if (y <=175){
y = MinH;
}
if(ax != 475 && ax < 475){
ax++;
}
if(ax >= 475 && ax != 60){
ax = ax - 475;
repaint();
}
if(x >= 468 && x <= 546){
y=385;
}
if(x >= 736 && x <= 826){
y=355;
}
if(x >= 160 && x <= 200 && y < 440 && y > 400){
y = MinH;
block1 = block;
}
if(x >= 264 && x <= 338 && y < 440 && y > 400){
y = MinH;
block3 = Bblock1;
}
if(x >= 339 && x <=410 && y < 440 && y > 400){
y = MinH;
block5 = Bblock2;
}
if (block1 == block && y >= 440){
c.drawImage(money, 210, 332,30,20, this);
}
if (block3 == Bblock1 && y >= 440){
c.drawImage(money, 337, 332,30,30, this);
}
if (block5 == Bblock2 && y >= 440){
c.drawImage(money, 395, 332,30,30, this);
}
wow++;
wow2++;
if(wow >= 20){
wow = 0;
}
if(wow <= 5 && right == true){
mario = walk2;
}
if(wow >= 5 && wow <=10 && right == true){
mario = walk2;
}
if(wow <= 10 && wow >=5 && right == true){
mario = walk5;
}
if(wow >= 10 && wow <=5 &&right == true){
mario = walk2;
}
if(wow2 >= 20){
wow2 = 0;
}
if(wow2 <= 5 && left == true){
mario = walk3;
}
if(wow2 >= 5 && left == true){
mario = walk6;
}
if(wow2 <= 10 && wow >=5 && left == true){
mario = walk6;
}
if(wow2 >= 10 && wow <=5 && left == true){
mario = walk3;
}
if(left == true){
x-=2;
}
if(right == true){
x+=2;
}
if(jump == true){
counter += 0.1;
y = y + (int) ((Math.sin(counter ) + Math.cos(counter))*15.5);
}
if(counter == 7){
counter = 4;
}
if(down == true){
y+=2;
}
if(y >= MinH ){
y = MinH;
}
System.out.println("(" + x + "," + y + ")");
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
#Override
public void keyTyped(KeyEvent e) {
// don't use
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == 37 ){
left = true;
}
if(e.getKeyCode() == 38){
jump = true;
mario = jumpR;
}
if(e.getKeyCode() == 39){
right = true;
}
if(e.getKeyCode() == 40){
down = true;
}
}
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == 37){
left = false;
mario = walk3;
}
if(e.getKeyCode() == 38){
jump = false;
mario = walk2;
counter = 4;
}
if(e.getKeyCode() == 39){
right = false;
mario = walk2;
}
if(e.getKeyCode() == 40){
down = false;
mario = walk2;
}
}
}
You need to keep up with states. For example you would have a START state and a RUNNING state. If the game is in the START state then you would draw the start screen, if it's in the RUNNING state you would draw your game. Later you may have a PAUSE state and a GAME_OVER state so you can show different screens there.
So to do this you will need a State enum like this:
public enum State
{
START, RUNNING, PAUSE, GAME_OVER;
}
Then in your GameLoop class create a variable to hold the current state.
private State state = State.START;
Then in your draw code and anywhere else necessary you can check the current state variable and draw the appropriate screen.
public void run()
{
switch(state)
{
case START:
//DRAW THE START SCREEN
break;
case RUNNING:
//DRAW THE GAME
break;
case PAUSE:
//DRAW THE PAUSE SCREEN
break;
case GAME_OVER:
//DRAW THE GAME OVER SCREEN
break;
default:
throw new RuntimeException("Unknown state: " + state);
}
}
A more clean solution would be to have a Screen class that has a draw method. Then your GameLoop just looks up the Screen associated with a given State and calls the draw method on it. This way your drawing code stays neatly tucked in to each Screen instead of all blobbed into one place. As your number of Screens grow you just add another Screen implementation. Here is some code to show what I mean:
Here is a Screen interface. You will have a Screen implementation for each State.
public interface Screen
{
void update();
void draw();
void handleInput();
}
Here is an empty example of a RunningScreen.
public class RunningScreen implements Screen
{
#Override
public void update()
{
//UPDATE LOGIC, MOVE ENTITIES OR WHATEVER
}
#Override
public void draw()
{
//DRAW THE RUNNING SCREEN
}
#Override
public void handleInput()
{
//CHECK FOR USER INPUT AND UPDATE THE SCREEN STATE
}
}
Here is an empty example of a StartScreen.
public class StartScreen implements Screen
{
#Override
public void update()
{
//UPDATE THE START SCREEN
}
#Override
public void draw()
{
//DRAW THE START SCREEN
}
#Override
public void handleInput()
{
//CHECK FOR INPUT, TRANSITION TO THE RUNNING SCREEN WHEN THE USER CLICKS START
}
}
Your game loop looks up the Screen that is registered to handle the current state, then calls the appropriate methods.
public class GameLoop
{
private State state = State.START;
private Map<State, Screen> screens = new HashMap<>();
public void addScreen(State state, Screen screen)
{
screens.put(state, screen);
}
public void run()
{
Screen screen = screens.get(state);
screen.handleInput();
screen.update();
screen.draw();
}
}
Then your Main might look something like this. It creates a new GameLoop and registers the Screens for each state.
public class Main
{
public static void main(String[] args)
{
GameLoop game = new GameLoop();
game.addScreen(State.START, new StartScreen());
game.addScreen(State.RUNNING, new RunningScreen());
//Add other states here
game.run();
}
}
I hope this gives you some ideas about how to implement the functionality you want.
i'm trying to create a game. And almost everytime I move, it's leaving a trail
Code:
package lt.mchackers.gametest.main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import lt.mchackers.gametest.handlers.InputHandler;
/**
* Main class for the game
*/
public class Main extends JFrame
{
private static final long serialVersionUID = -828018325337767157L;
boolean isRunning = true;
int fps = 30;
int windowWidth = 320;
int windowHeight = 320;
int speed;
BufferedImage backBuffer;
Insets insets;
InputHandler input;
int x = 0;
int y = 0;
int xa = 0;
int ya = 0;
Coordinates coords = new Coordinates(0, 0);
public static void main(String[] args)
{ Main game = new Main();
game.run();
System.exit(0);
}
/**
* This method starts the game and runs it in a loop
*/
public void run()
{
initialize();
while(isRunning)
{
long time = System.currentTimeMillis();
update();
draw();
// delay for each frame - time it took for one frame
time = (1000 / fps) - (System.currentTimeMillis() - time);
if (time > 0)
{
try
{
Thread.sleep(time);
}
catch(Exception e){}
}
}
setVisible(false);
}
/**
* This method will set up everything need for the game to run
*/
void initialize()
{
setTitle("Game Tutorial");
setSize(windowWidth, windowHeight);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
insets = getInsets();
setSize(insets.left + windowWidth + insets.right,
insets.top + windowHeight + insets.bottom);
backBuffer = new BufferedImage(windowWidth, windowHeight, BufferedImage.TYPE_INT_RGB);
input = new InputHandler(this);
Graphics bbg = backBuffer.getGraphics();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("map"));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
String line = null;
try {
BufferedImage gray = ImageIO.read(new File("gray.png"));
BufferedImage black = ImageIO.read(new File("black.png"));
while ((line = reader.readLine()) != null) {
for(String s : line.split(""))
{
if (s.contains("*"))
{
bbg.drawImage(gray, xa-32, ya, null);
}
else if (s.contains("#"))
{
bbg.drawImage(black, xa-32, ya, null);
}
if (xa < 320)
{
xa += 32;
}
else
{
ya += 32;
xa = 0;
}
System.out.println(xa);
System.out.println(ya);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* This method will check for input, move things
* around and check for win conditions, etc
*/
void update()
{
if (input.isKeyDown(KeyEvent.VK_NUMPAD0))
{
speed -= 1;
}
if (input.isKeyDown(KeyEvent.VK_NUMPAD1))
{
speed += 1;
}
if (input.isKeyDown(KeyEvent.VK_RIGHT))
{
coords.setCoords(coords.getX() + 32, coords.getY());
}
if (input.isKeyDown(KeyEvent.VK_LEFT))
{
coords.setCoords(coords.getX() - 32, coords.getY());
}
if (input.isKeyDown(KeyEvent.VK_UP))
{
coords.setCoords(coords.getX(), coords.getY() - 32);
}
if (input.isKeyDown(KeyEvent.VK_DOWN))
{
coords.setCoords(coords.getX(), coords.getY() + 32);
}
//System.out.println(x);
//System.out.println(y);
//System.out.println(speed);
if (coords.getY() < 0)
{
coords.setCoords(coords.getX(), 0);
}
if (coords.getX() < 0)
{
coords.setCoords(0, coords.getY());
}
if (coords.getX() > windowWidth - 32)
{
coords.setCoords(windowWidth - 32, coords.getY());
}
if (coords.getY() > windowHeight - 32)
{
coords.setCoords(coords.getX(), windowHeight - 32);
// y = windowHeight - 32;
}
}
/**
* This method will draw everything
*/
void draw()
{
Graphics g = getGraphics();
//this.setBackground(Color.BLACK);
//super.paintComponents(g);
backBuffer.setRGB(x, y, Color.BLACK.getRGB());
Graphics bbg = backBuffer.getGraphics();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("map"));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
String line = null;
try {
BufferedImage gray = ImageIO.read(new File("gray.png"));
BufferedImage black = ImageIO.read(new File("black.png"));
while ((line = reader.readLine()) != null) {
for(String s : line.split(""))
{
if (s.contains("*") && xa + 32!= coords.getX() && ya - 32 != coords.getY())
{
bbg.drawImage(gray, xa-32, ya, null);
}
else if (s.contains("#") && xa + 32 != coords.getX() && ya - 32 != coords.getY())
{
bbg.drawImage(black, xa-32, ya, null);
}
if (xa < 320)
{
xa += 32;
}
else
{
ya += 32;
xa = 0;
}
//System.out.println(xa);
//System.out.println(ya);
}
}
} catch (IOException e) {
e.printStackTrace();
}
bbg.setColor(Color.WHITE);
xa = 0;
ya = 0;
System.out.println(coords.getX());
bbg.setColor(Color.WHITE);
bbg.fillRect(coords.getX(),coords.getY(), 32,32);
System.out.println(coords.getY());
//bbg.setColor(Color.BLACK);
//bbg.drawOval(x, y, 20, 20);
g.drawImage(backBuffer, insets.left, insets.top, this);
}
}
Thanks for help.
Check out my code from here, to get a hint as to how to paint stuff in a game loop properly.
Basically what you need to take care of is double buffering to prevent any flickering and also repainting the background so that you don't leave out any trail of rectangles.
You can also check out the Killer Game Programming in Java online book, which can help you learn the game programming concepts and their implementation.
The concept of double buffering is simple. Since painting on the screen takes more time than updating the states of the objects in the gameplay, we use two canvas to prevent any flickering issues which arise when objects are painted directly on the screen.
When the object states are updated in the game loop, it is rendered in a background canvas. The background canvas is then copied to the screen which takes less time compared to painting directly on the screen. And while this copying is happening, the object states are updated again and they are rendered on the background canvas again, which is then copied to the screen. Repeat this over and over, and you get the double buffering.
Basically you keep a buffer of screen which is to be painted and your game renders objects in the buffer which is then copied to the screen.
Here's a code which I think might help you understand the concept:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class GamePanel extends JPanel implements Runnable
{
private static final long serialVersionUID = 6892533030374996243L;
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
private Thread animator;
private volatile boolean running = false;
private volatile boolean isGameOver = false;
private volatile boolean isUserPaused = false;
private volatile boolean isWindowPaused = false;
private Graphics dbg;
private Image dbImage = null;
private static final int NO_DELAYS_PER_YIELD = 16;
private static final int MAX_FRAME_SKIPS = 5;
private static final Color backgroundColor = new Color(245, 245, 245);
private static long fps = 30;
private static long period = 1000000L * (long) 1000.0 / fps;
private static volatile boolean isPainted = false;
public GamePanel()
{
setBackground(backgroundColor);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
requestFocus();
readyForPause();
// Add key listeners here...
}
public void addNotify()
{
super.addNotify();
startGame();
}
void startGame()
{
if (animator == null || !running)
{
animator = new Thread(this);
animator.start();
}
}
void stopGame()
{
running = false;
}
private void readyForPause()
{
addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
if ((keyCode == KeyEvent.VK_ESCAPE) || (keyCode == KeyEvent.VK_Q)
|| (keyCode == KeyEvent.VK_END) || (keyCode == KeyEvent.VK_P)
|| ((keyCode == KeyEvent.VK_C) && e.isControlDown()))
{
if (!isUserPaused)
setUserPaused(true);
else
setUserPaused(false);
}
}
});
}
// This is the game loop. You can copy-paste it even in your own code if you want to.
public void run()
{
long beforeTime, afterTime, timeDiff, sleepTime;
long overSleepTime = 0L;
int noDelays = 0;
long excess = 0L;
beforeTime = System.nanoTime();
running = true;
while (running)
{
requestFocus();
gameUpdate();
gameRender();
paintScreen();
afterTime = System.nanoTime();
timeDiff = afterTime - beforeTime;
sleepTime = (period - timeDiff) - overSleepTime;
if (sleepTime > 0)
{
try
{
Thread.sleep(sleepTime / 1000000L);
}
catch (InterruptedException e)
{
}
overSleepTime = (System.nanoTime() - afterTime - sleepTime);
}
else
{
excess -= sleepTime;
overSleepTime = 0L;
if (++noDelays >= NO_DELAYS_PER_YIELD)
{
Thread.yield();
noDelays = 0;
}
}
beforeTime = System.nanoTime();
int skips = 0;
while ((excess > period) && (skips < MAX_FRAME_SKIPS))
{
excess -= period;
gameUpdate();
skips++;
}
isPainted = true;
}
System.exit(0);
}
private void gameUpdate()
{
if (!isUserPaused && !isWindowPaused && !isGameOver)
{
// Update the state of your game objects here...
}
}
private void gameRender()
{
if (dbImage == null)
{
dbImage = createImage(WIDTH, HEIGHT);
if (dbImage == null)
{
System.out.println("Image is null.");
return;
}
else
dbg = dbImage.getGraphics();
}
dbg.setColor(backgroundColor);
dbg.fillRect(0, 0, WIDTH, HEIGHT);
// Render your game objects here....
// like: xyzObject.draw(dbg);
// or dbg.drawOval(...);
if (isGameOver)
gameOverMessage(dbg);
}
private void gameOverMessage(Graphics g)
{
// Paint a game over message here..
}
private void paintScreen()
{
Graphics g;
try
{
g = this.getGraphics();
if ((g != null) && (dbImage != null))
g.drawImage(dbImage, 0, 0, null);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
catch (Exception e)
{
System.out.println("Graphics context error : " + e);
}
}
public void setWindowPaused(boolean isPaused)
{
isWindowPaused = isPaused;
}
public void setUserPaused(boolean isPaused)
{
isUserPaused = isPaused;
}
}
Then you can simply add your game panel to your JFrame like following:
import java.awt.GridBagLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class GameFrame extends JFrame
{
private static final long serialVersionUID = -1624735497099558420L;
private GameFrame gamePanel = new GamePanel();
public GameFrame()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Game");
addWindowListener(new FrameListener());
getContentPane().setLayout(new GridBagLayout());
getContentPane().add(gamePanel);
pack();
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
}
public class FrameListener extends WindowAdapter
{
public void windowActivated(WindowEvent we)
{
gamePanel.setWindowPaused(false);
}
public void windowDeactivated(WindowEvent we)
{
gamePanel.setWindowPaused(true);
}
public void windowDeiconified(WindowEvent we)
{
gamePanel.setWindowPaused(false);
}
public void windowIconified(WindowEvent we)
{
gamePanel.setWindowPaused(true);
}
public void windowClosing(WindowEvent we)
{
gamePanel.stopGame();
}
}
public static void main(String args[])
{
new GameFrame();
}
}
Why does the height of the rectangle's jump vary? It seems to go in a cycle. First it jumps low then it doesn't jump at all then it jumps high then it doesn't jump at all. i can't figure out why as the same code is used and it is triggered by the same event.
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
class Game extends JPanel{
Square square = new Square(this);
Ground ground = new Ground (this);
public Game() {
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
square.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
square.keyPressed(e);
}
});
setFocusable(true);
}
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("My Mario");
Game game = new Game();
frame.add(game);
frame.setSize(600, 700);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
game.move();
game.repaint();
Thread.sleep(30);
}
}
private void move() {
square.move();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
square.paint(g2d);
ground.paint(g2d);
}
}
public class Square {
Square square;
int x,xa;
static int y;
int ya;
private Game game;
public static int fistX,fistY;
static int d = 60;
int wide;
boolean onGround;
public Square(Game game) {
this.game = game;
x = 100;
y = 631;
xa = 0;
ya = 0;
onGround = false;
wide = game.getWidth();
}
public void move() {
if (x + xa > 0 && x + xa < game.getWidth()-30)
x = x + xa;
if (y + ya > 0 && y + ya < game.getHeight()-60){
for(int i=12; i< 0; i--);
ya+=10;
y = y + ya;
}
if ( collision() ) {
y-=10;
onGround = true;
}
Square.y+=10;
}
public void paint(Graphics2D g) {
g.setColor(Color.RED);
g.fillRoundRect(x, y-d, 30, d, 10, 10);
}
private boolean collision() {
return game.ground.getBounds().intersects(getBounds());
}
public Rectangle getBounds() {
return new Rectangle(x, y, 30, 60);
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa=0;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa=0;
if(e.getKeyCode() == KeyEvent.VK_DOWN)
d = 60;
if(e.getKeyCode() == KeyEvent.VK_UP);
}
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa = xa -3;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = xa + 3;
if(e.getKeyCode() == KeyEvent.VK_DOWN)
d = 30;
if(e.getKeyCode() == KeyEvent.VK_UP)
ya -= 60;
}
}
class Ground {
int y,x,h,w;
public Ground(Game game){
x = 0;
y = game.getHeight()-30;
w = game.getWidth();
h = 30;
}
public void paint(Graphics2D g){
g.setColor(Color.BLACK);
g.fillRect(0, 700, 99999999, 30);
}
public Rectangle getBounds() {
return new Rectangle(0, 700, 99999999, 30);
}
}
Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling Thread.sleep(n) implement a Swing Timer for repeated tasks like animation. See Concurrency in Swing for more details.
frame.setSize(600, 700); I recommend instead setting a preferred size for the content and packing the frame around it. This suggests a constant size for the game on different PLAFs or OS'.
For Swing components other than top-level containers (e.g JFrame or JWindow), override paintComponent(Graphics) rather than paint(Graphics).
Look into key bindings instead of key listeners for Swing.
The first 3 are implemented, the last one (and other one commented in the code) is TODO - BNI.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class SuperMarioGame extends JPanel {
private static final long serialVersionUID = 1L;
Square square = new Square(this);
Ground ground = new Ground (this);
public SuperMarioGame() {
// TODO Update to Key Bindings
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
square.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
square.keyPressed(e);
}
});
setFocusable(true);
// Use a listener/timer combo.
ActionListener gameAnimation = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
move();
repaint();
}
};
Timer timer = new Timer(30,gameAnimation);
timer.start();
// Set a preferred size for the panel.
Dimension preferred = new Dimension(600,700);
this.setPreferredSize(preferred);
}
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("My Mario");
SuperMarioGame game = new SuperMarioGame();
frame.add(game);
// Pack the frame to the preferred size.
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void move() {
square.move();
}
#Override
// for Swing components, generally override
// paintComponent rather than paint
//public void paint(Graphics g) {
public void paintComponent(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
square.paint(g2d);
ground.paint(g2d);
}
}
class Square {
Square square;
int x,xa;
static int y;
int ya;
private SuperMarioGame game;
public static int fistX,fistY;
static int d = 60;
int wide;
boolean onGround;
public Square(SuperMarioGame game) {
this.game = game;
x = 100;
y = 631;
xa = 0;
ya = 0;
onGround = false;
wide = game.getWidth();
}
public void move() {
if (x + xa > 0 && x + xa < game.getWidth()-30)
x = x + xa;
if (y + ya > 0 && y + ya < game.getHeight()-60){
for(int i=12; i< 0; i--);
ya+=10;
y = y + ya;
}
if ( collision() ) {
y-=10;
onGround = true;
}
Square.y+=10;
}
public void paint(Graphics2D g) {
g.setColor(Color.RED);
g.fillRoundRect(x, y-d, 30, d, 10, 10);
}
private boolean collision() {
return game.ground.getBounds().intersects(getBounds());
}
public Rectangle getBounds() {
return new Rectangle(x, y, 30, 60);
}
public void keyReleased(KeyEvent e) {
// TODO Else-if would be better here..
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa=0;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa=0;
if(e.getKeyCode() == KeyEvent.VK_DOWN)
d = 60;
if(e.getKeyCode() == KeyEvent.VK_UP);
}
public void keyPressed(KeyEvent e) {
// TODO Else-if would be better here..
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa = xa -3;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = xa + 3;
if(e.getKeyCode() == KeyEvent.VK_DOWN)
d = 30;
if(e.getKeyCode() == KeyEvent.VK_UP)
ya -= 60;
}
}
class Ground {
int y,x,h,w;
public Ground(SuperMarioGame game){
x = 0;
y = game.getHeight()-30;
w = game.getWidth();
h = 30;
}
public void paint(Graphics2D g){
g.setColor(Color.BLACK);
g.fillRect(0, 700, 99999999, 30);
}
public Rectangle getBounds() {
return new Rectangle(0, 700, 99999999, 30);
}
}
Don't block the Event Dispatching Thread any way, it will prevent the EDT from processing repaint requests (and other events) which will make it look like your program has crashed. Have a read of Concurrency in Swing for more information.
Only modify the UI from the EDT, NEVER from any other thread, this includes creating UI elements
Favor key bindings over KeyListeners, they are more capable of resolving focus issues amongst other things. Have a read of How to Use Key Bindings for more details
Favor overriding paintComponent rather then paint. Paint does a lot of important work which you should avoid messing with if you can. Apart from any thing else paintComponent is going to be included in the double buffering of the component where as paint isn't (as super.paint sets it up)
Avoid using static state variables where possible
I don't know if this was deliberate or not, but, for (int i = 12; i < 0; i--); isn't going to achive anything, as the semi colen at the end means, do nothing for a count of 1
Personally, try not to use absolute values for things like width and height, which is actually reliant on parent container. You should also, where possible, provide sizing hints to allow the parent container to make better decisions on how much space it actually needs
UPDATED
Fixed bug in my movement code :P
I had a look at your collision detection code (in move) and, frankly, couldn't make heads or tails of it. I corrected it as well as changed in the way the paint method works so that x,y is always the top, left corner
public class TestGame {
public static void main(String[] args) throws InterruptedException {
new TestGame();
}
public TestGame() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
Game game = new Game();
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GameThread extends Thread {
private Game game;
public GameThread(Game game) {
setDaemon(false);
this.game = game;
}
#Override
public void run() {
while (true) {
game.move();
try {
long startedAt = System.currentTimeMillis();
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
game.repaint();
}
});
long completedAt = System.currentTimeMillis();
long sleepFor = 30 - (completedAt - startedAt);
if (sleepFor < 0) {
sleepFor = 30;
}
Thread.sleep(sleepFor);
} catch (Exception exp) {
exp.printStackTrace();
}
}
}
}
public class Game extends JPanel {
Square square = new Square(this);
Ground ground = new Ground(this);
public Game() {
// addKeyListener(new KeyListener() {
// #Override
// public void keyTyped(KeyEvent e) {
// }
//
// #Override
// public void keyReleased(KeyEvent e) {
// square.keyReleased(e);
// }
//
// #Override
// public void keyPressed(KeyEvent e) {
// square.keyPressed(e);
// }
// });
setFocusable(true);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "press-left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "press-right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "press-down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "press-up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "release-left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "release-right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "release-down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "release-up");
am.put("press-left", new PressLeftAction(square));
am.put("press-right", new PressRightAction(square));
am.put("press-down", new PressDownAction(square));
am.put("press-up", new PressUpAction(square));
am.put("release-left", new ReleaseLeftAction(square));
am.put("release-right", new ReleaseRightAction(square));
am.put("release-down", new ReleaseDownAction(square));
am.put("release-up", new ReleaseUpAction(square));
new GameThread(this).start();
// public void keyReleased(KeyEvent e) {
//
//
//
// if (e.getKeyCode() == KeyEvent.VK_LEFT) {
// xa = 0;
// }
//
// if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
// xa = 0;
// }
// if (e.getKeyCode() == KeyEvent.VK_DOWN) {
// d = 60;
// }
//
// if (e.getKeyCode() == KeyEvent.VK_UP);
// }
//
// public void keyPressed(KeyEvent e) {
//// TODO Auto-generated method stub
// if (e.getKeyCode() == KeyEvent.VK_LEFT) {
// xa = xa - 3;
// }
//
// if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
// xa = xa + 3;
// }
//
// if (e.getKeyCode() == KeyEvent.VK_DOWN) {
// d = 30;
// }
//
// if (e.getKeyCode() == KeyEvent.VK_UP) {
// ya -= 60;
// }
//
//
//
//
//
// }
}
public void move() {
square.move();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
// Don't override paint, use paintComponent instead
// #Override
// public void paint(Graphics g) {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
square.paint(g2d);
ground.paint(g2d);
g2d.dispose();
}
}
public class Square {
Square square;
private int x, xa;
// static int y;
private int y;
private int ya;
private Game game;
// public static int fistX, fistY;
private int fistX, fistY;
// static int d = 60;
private int d = 60;
private int wide;
private boolean onGround;
public Square(Game game) {
this.game = game;
x = 100;
y = 100;
xa = 0;
ya = 0;
onGround = false;
wide = game.getWidth();
}
public void move() {
y += ya;
x += xa;
if (x < 0) {
x = 0;
} else if (x + 30 > game.getWidth()) {
x = game.getWidth() - 30;
}
if (y < 0) {
y = 0;
} else if (collision()) {
onGround = true;
y = game.ground.getBounds().y - d;
}
// if (x + xa > 0 && x + xa < game.getWidth() - 30) {
// x = x + xa;
// }
//
// if (y + ya > 0 && y + ya < game.getHeight() - 60) {
// // This was never going to do anything, look at the
// // end of the line...the `;` is going to prevent the
// // statemt ya += 10 from begin called within the loop
//// for (int i = 12; i < 0; i--);
// for (int i = 12; i < 0; i--) {
// ya += 10;
// }
// y = y + ya;
// }
// if (collision()) {
// y -= 10;
// onGround = true;
//
// }
//
// y += 10;
}
public void paint(Graphics2D g) {
g.setColor(Color.RED);
System.out.println(x + "x" + (y - d));
g.fillRoundRect(x, y, 30, d, 10, 10);
}
private boolean collision() {
return game.ground.getBounds().intersects(getBounds());
}
public Rectangle getBounds() {
return new Rectangle(x, y, 30, 60);
}
}
public class Ground {
private Game game;
public Ground(Game game) {
this.game = game;
}
public void paint(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillRect(0, game.getHeight() - 30, game.getWidth(), 30);
}
public Rectangle getBounds() {
return new Rectangle(0, game.getHeight() - 30, game.getWidth(), 30);
}
}
public abstract class AbstractSquareAction extends AbstractAction {
private Square square;
public AbstractSquareAction(Square square) {
this.square = square;
}
public Square getSquare() {
return square;
}
}
public class PressLeftAction extends AbstractSquareAction {
public PressLeftAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().xa = -3;
System.out.println("pressLeft");
}
}
public class PressRightAction extends AbstractSquareAction {
public PressRightAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().xa = 3;
}
}
public class PressDownAction extends AbstractSquareAction {
public PressDownAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().ya = 30;
}
}
public class PressUpAction extends AbstractSquareAction {
public PressUpAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().ya -= 30;
}
}
public class ReleaseLeftAction extends AbstractSquareAction {
public ReleaseLeftAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().xa = 0;
}
}
public class ReleaseRightAction extends AbstractSquareAction {
public ReleaseRightAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().xa = 0;
}
}
public class ReleaseDownAction extends AbstractSquareAction {
public ReleaseDownAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().ya = 0;
}
}
public class ReleaseUpAction extends AbstractSquareAction {
public ReleaseUpAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().ya = 0;
}
}
}
I'm trying to create a simple sideScroller in java, so far my game runs as expected but i have no idea on how to create a pause menu to go to the main menu and stuff (haven't got any idea on how to create a main manu for that mater) what do you think it's the best idea? this is the relevant code of my game, this panel is called inside a frame:
Game Code
package videojuegoalpha;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Background extends JPanel implements ActionListener, Runnable {
BufferedImage img, marco;
Character character;
Obstacle[] obstacleArray;
Timer time;
//CONSTANTS
final static int largoPantalla = 800;
final static int borderWidth=24;
final static int diferencialPantalla = 74;
final static int characterFlow=10;
final static int fontSize=18;
final static int flickerTime=150;
final static int invincibilityTime=2000;
int largonivel;
int controlPaso;
int actualHeight;
int standardHeight;
int maxHeightValue;
int deltaObstaculo;
Thread brinco;
static boolean debug=false;
boolean jumpCycleDone;
boolean runDone;
boolean maxHeight;
boolean shrinkHeart;
boolean pause;
static Font fontScore,fontMultiplier;
Lives lives;
static MultithreadSystem sounds = new MultithreadSystem();
static Thread MusicPlayer = new Thread(sounds);
static String BackgroundMusic;
String hitSound;
String score;
public Background(int actualHeight, int maxHeightValue,
String characterImage,String characterHitImage, int pasosPersonaje,int speed,
String imagenFondo,String imagenMarco,
String lowObstacleImage,String highObstacleImage,int obstacleDistance,
String musicFile,String jumpSound,String hitSound, String dashSound) {
controlPaso=0;
this.standardHeight = actualHeight;
this.actualHeight = this.standardHeight;
this.maxHeightValue = maxHeightValue;
jumpCycleDone = false;
runDone = false;
maxHeight = false;
shrinkHeart=false;
pause=false;
character = new Character(characterImage,characterHitImage,pasosPersonaje,
speed,jumpSound,dashSound);
lives=new Lives();
obstacleArray=Obstacle.getObstacleArray(5200,obstacleDistance,
standardHeight+deltaObstaculo+borderWidth, (standardHeight+deltaObstaculo)/,lowObstacleImage,highObstacleImage);
addKeyListener(new AL());
setFocusable(true);
try {
img = CompatibleImage.toCompatibleImage(ImageIO.read(new File(
"Images"+File.separator+"Background"+
File.separator+imagenFondo)));
marco = CompatibleImage.toCompatibleImage(ImageIO.read(new File(
"Images"+File.separator+imagenMarco)));
fontScore=(Font.createFont(Font.TRUETYPE_FONT,new FileInputStream(new File(
"Fonts"+File.separator+"score.ttf")))).deriveFont(Font.BOLD, 18);
fontMultiplier=(Font.createFont(Font.TRUETYPE_FONT,
new FileInputStream(new File("Fonts"+File.separator+"multi.ttf"))))
.deriveFont(Font.BOLD, fontSize+10);
} catch (IOException | FontFormatException e) {
System.out.println("Error al cargar" + ":" + e.toString());
}
deltaObstaculo=(character.getImage(character.pasoActual).
getHeight(null))- (obstacleArray[0].getImage().getHeight(null));
time = new Timer(5, this);
time.start();
BackgroundMusic = "Music/"+musicFile;
backMusic(BackgroundMusic);
this.hitSound=hitSound;
}
public static void backMusic(String MusisBck) {
sounds.newThread(BackgroundMusic);
MusicPlayer.start();
if (MusicPlayer.isAlive() != true) {
sounds.newThread(BackgroundMusic);
MusicPlayer.start();
}
}
#Override
public void actionPerformed(ActionEvent e) {
if(!pause){
character.move();
}
condWin(5200);
condLose();
avanzaPaso();
repaint();
}
public void avanzaPaso() {
if(!pause){
controlPaso++;
}
if (controlPaso % characterFlow == 0) {
character.pasoActual++;
if (character.pasoActual > character.pasos-3) {
character.pasoActual = 0;
}
debugMode("Paso: " + character.pasoActual);
}
if(controlPaso%(characterFlow*(character.pasos-2))==0){
shrinkHeart = !shrinkHeart;//oscilaciĆ³n para encojer/desencojer
}
}
public void condWin(int dist) {
if (character.getPositionX() == dist) {
MultithreadSystem sounds = new MultithreadSystem();
sounds.newThread("Music/FF3Victory.wav");
Thread sounds_player = new Thread(sounds);
MusicPlayer.stop();
sounds_player.start();
JOptionPane.showMessageDialog(null, "YOU WIN!");
System.exit(0);
}
}
public void condLose() {
if (character.lives == 0) {
character.isAlive = false;
if (!character.isAlive) {
MultithreadSystem sounds = new MultithreadSystem();
sounds.newThread("Music/gameOver01.wav");
Thread sounds_player = new Thread(sounds);
MusicPlayer.stop();
sounds_player.start();
JOptionPane.showMessageDialog(null, "YOU SUCK");
System.exit(0);
}
}
}
#Override
public void paint(Graphics g) {
debugMode("Altura: " + actualHeight);
if (character.deltaY == 1 && runDone == false) {
runDone = true;
brinco = new Thread(this);
brinco.start();
}
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img, largoPantalla - character.getnX2(), 0, null);
if (character.getPositionX() > diferencialPantalla) {
g2d.drawImage(img, largoPantalla - character.getnX(), 0, null);
}
for (int i = 0; i < obstacleArray.length; i++) {
if (obstacleArray[i] != null) {
if (obstacleArray[i].getPositionX() == -character.posicionFija) {
obstacleArray[i] = null;
}
if (obstacleArray[i] != null) {
if(!pause){
obstacleArray[i].move(character.pixPerStep);
}
if (obstacleArray[i].getPositionX() ==
largoPantalla + character.posicionFija) {
obstacleArray[i].setVisible(true);
}
if (obstacleArray[i].isVisible()) {
g2d.drawImage(obstacleArray[i].getImage(),
obstacleArray[i].getPositionX(),
obstacleArray[i].getPositionY(), null);
}
checkCollisions(obstacleArray[i]);
}
}
}
if (character.paintCharacter) {
g2d.drawImage(character.getImage(character.pasoActual),
character.posicionFija, actualHeight, null);
}
character.hit(flickerTime);
if (shrinkHeart) {
g2d.drawImage(lives.getImage(character.getLives()),
borderWidth + 5,
borderWidth + 5,
(int) (lives.getImage(character.getLives()).getWidth() * .95),
(int) (lives.getImage(character.getLives()).getHeight() * .95),
null);
} else {
g2d.drawImage(lives.getImage(character.getLives()),
borderWidth + 5,
borderWidth + 5,
null);
}
g2d.drawImage(marco, 0, 0, null);
g2d.setFont(fontScore);
g2d.setColor(Color.BLACK);
score = String.format("%08d", character.score);
g2d.drawString("score:" + score, 500, borderWidth * 2);
g2d.setFont(fontMultiplier);
g2d.drawString(character.multiplier + "",
(largoPantalla / 2) - 75, (borderWidth * 2) + 10);
}
private class AL extends KeyAdapter {
#Override
public void keyReleased(KeyEvent e) {
character.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(!pause){
character.keyPressed(e);
}
if (key == KeyEvent.VK_D) {
debug=(!debug);
}
if(key==KeyEvent.VK_P){
pause=(!pause);
}
if (key == KeyEvent.VK_ESCAPE) {
System.exit(0);
}
}
}
public void checkCollisions(Obstacle obstacle) {
if (character.posicionFija == obstacle.getPositionX()) {
if (obstacle instanceof LowObstacle) {
debugMode("Obstaculo Bajo, Altura: "+obstacle.getPositionY());
if (actualHeight <= (standardHeight - obstacle.getImage().getHeight(null))){
if (character.multiplier < 4) {
character.multiplier++;
}
} else {
if (character.hitAllowed) {
sounds = new MultithreadSystem();
sounds.newThread("SFX/" + hitSound);
Thread sounds_player = new Thread(sounds);
sounds_player.start();
character.multiplier = 1;
character.lives--;
character.hitAllowed = false;
}
}
}
else{
debugMode("Obstaculo Alto, Altura: "+obstacle.getPositionY());
if (character.dashPressed) {
if (character.multiplier < 4) {
character.multiplier++;
}
} else {
if (character.hitAllowed) {
sounds = new MultithreadSystem();
sounds.newThread("SFX/" + hitSound);
Thread sounds_player = new Thread(sounds);
sounds_player.start();
character.multiplier = 1;
character.lives--;
character.hitAllowed = false;
}
}
}
}
}
public void cycle() {
if(!pause){
if (maxHeight == false) {
actualHeight--;
}
if (actualHeight == maxHeightValue) {
maxHeight = true;
}
if (maxHeight == true && actualHeight <= standardHeight) {
actualHeight++;
if (actualHeight == standardHeight) {
jumpCycleDone = true;
}
}
}
}
#Override
public void run() {
character.isJumping = true;
character.keyAllowed = false;
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (jumpCycleDone == false) {
cycle();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = 8 - timeDiff;
if (sleep < 0) {
sleep = 2;
}
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
}
beforeTime = System.currentTimeMillis();
}
jumpCycleDone = false;
maxHeight = false;
runDone = false;
character.keyAllowed = true;
character.isJumping = false;
}
public static void debugMode(String string){
if(debug){
System.out.println(string);
}
}
// Getters y Setters //
public Character getCharacter() {
return character;
}
public void setCharacter(Character character) {
this.character = character;
}
}
As you can see I already have a pause variable which pauses everything, but I would like to have a little window popup in the middle while pause its true
The problem is that your class Background is directly where you draw.
Normally your game handles all the frames and stuff, but then you have some kind of GameState object which your main game calls, like this:
public void update() {
if (pause) {
gameState = pauseState;
} else {
gameState = playState;
}
gameState.update();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
gameState.paint(g2d)
}
The idea is that you can have as many gameStates as you want. Simply make an interface GameState that provides methods for Update, Paint, Initialize and Dispose (or something like this).
Then you can have all kinds of GameStates, for example Play, Pause, MainMenu, SaveGameMenu, etc., each one in charge of updating and drawing itself.
It's the main class (where your game loop is) where you handle the logic to swap the GameStates.