I'm in the process of developing a java applet game following a tutorial found here: http://www.kilobolt.com/unit-2-creating-a-game-i.html
I'm using this as a foundation to extend my own app. But here is the problem.
I want to add JButtons to the applet for certain features (start, options etc). But I found them to be flickering when i hover over them and completely hidden if left untouched. I read that it has to do with double buffering and that I should use the paintComponent rather than paint eg
public void paintComponents(Graphics g) {
super.paintComponents(g);
}
That solves the Jbuttons from flickering but then the g.drawimage methods are broke or I don't understand it fully, as the images I'm trying to draw are not showing. I don't know if they are hidden or can't be load or what. If someone could please point to the right direction that would be great.
public class StartingClass extends Applet implements Runnable, KeyListener, ActionListener {
private PlayerChar playerChar;
private Image image, currentSprite, character, characterDown, characterJumped, background;
private Graphics second;
private URL base;
private static Background bg1, bg2;
private JButton start, options;
private boolean running = false;
private int score;
#Override
public void init() {
setSize(800, 480);
setFocusable(true);
addKeyListener(this);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("GraviOn-Alpha");
try {
base = getDocumentBase();
}
catch (Exception e) {
// TODO: handle exception
}
// Image Setups
character = getImage(base, "data/character.png");
characterDown = getImage(base, "data/down.png");
characterJumped = getImage(base, "data/jumped.png");
currentSprite = character;
background = getImage(base, "data/background.png");
score = 0;
}
#Override
public void start() {
bg1 = new Background(0, 0);
bg2 = new Background(2160, 0);
playerChar = new PlayerChar();
JPanel myPanel = new JPanel();
start = new JButton("Start");
start.addActionListener(this);
options = new JButton("Change Colour");
options.addActionListener(this);
myPanel.add(start);
myPanel.add(options);
myPanel.setBackground(Color.BLACK);
myPanel.setPreferredSize(new Dimension(100, 75));
this.add(myPanel);
Thread thread = new Thread(this);
thread.start();
}
#Override
public void stop() {
// TODO Auto-generated method stub
}
#Override
public void destroy() {
// TODO Auto-generated method stub
}
#Override
public void run() {
while (true) {
if (running == true) {
playerChar.moveRight();
score += 3;
start.setVisible(false);
options.setVisible(false);
}
else {
}
playerChar.update();
if (playerChar.isJumped()) {
currentSprite = characterJumped;
}
else if (playerChar.isJumped() == false && playerChar.isDucked() == false) {
currentSprite = character;
}
bg1.update();
bg2.update();
repaint();
try {
Thread.sleep(17);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void update(Graphics g) {
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
second = image.getGraphics();
}
second.setColor(getBackground());
second.fillRect(0, 0, getWidth(), getHeight());
second.setColor(getForeground());
paint(second);
g.drawImage(image, 0, 0, this);
}
#Override
public void paintComponents(Graphics g) {
super.paintComponents(g);
g.drawImage(background, bg1.getBgX(), bg1.getBgY(), this);
g.drawImage(background, bg2.getBgX(), bg2.getBgY(), this);
g.drawImage(currentSprite, playerChar.getCenterX() - 61, playerChar.getCenterY() - 63, this);
g.drawString("Score: " + score, 50, 50);
}
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Move up");
break;
case KeyEvent.VK_DOWN:
currentSprite = characterDown;
if (playerChar.isJumped() == false) {
playerChar.setDucked(true);
playerChar.setSpeedX(0);
}
break;
case KeyEvent.VK_LEFT:
// playerChar.moveLeft();
playerChar.setMovingLeft(true);
break;
case KeyEvent.VK_RIGHT:
// playerChar.moveRight();
playerChar.setMovingRight(true);
break;
case KeyEvent.VK_SPACE:
playerChar.jump();
break;
}
}
#Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Stop moving up");
break;
case KeyEvent.VK_DOWN:
currentSprite = character;
playerChar.setDucked(false);
break;
case KeyEvent.VK_LEFT:
playerChar.stopLeft();
break;
case KeyEvent.VK_RIGHT:
playerChar.stopRight();
break;
case KeyEvent.VK_SPACE:
break;
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
public static Background getBg1() {
return bg1;
}
public static Background getBg2() {
return bg2;
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Start")) {
running = true;
}
if (e.getActionCommand().equals("Change Colour") && character == getImage(base, "data/character.png")) {
character = getImage(base, "data/character2.png");
}
else if (e.getActionCommand().equals("Change Colour") && character == getImage(base, "data/character2.png")) {
character = getImage(base, "data/character.png");
}
repaint();
}
}
This is with trying to utilize the paintComponents method. I would greatly appreciate help.
EDIT: I have changed to using Japplet and used paintComponent in a Jpanel to draw everything and it worked fine, all based on JApplet - super.paint(); causes flicker.
I have changed to using Japplet and used paintComponent in a Jpanel to draw everything and it worked fine.
JPanel myPanel = new JPanel(){
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, bg1.getBgX(), bg1.getBgY(), this);
g.drawImage(background, bg2.getBgX(), bg2.getBgY(), this);
g.drawImage(currentSprite, playerChar.getCenterX() - 61, playerChar.getCenterY() - 63, this);
g.drawString("Score: " + score, 50, 50);
}
Related
I am fairly new to Java and programming in general. I am developing a small game where the user plays as a white square whose objective is to collect all of the coins on screen. As the user collects coins moving red squares appear on the screen that will end the game if the user touches them. I use KeyListener to move the user's square.
The problem I am encountering is that I cannot move the player's square while a red square is moving. The red square will move when a while loop is activated within the paint method. I would like the user to be able to move their square while a red square is moving.
Here is my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFrame;
public class FinalGame extends Canvas
{
private static final long serialVersionUID =1L;
//refers to players coordinates
static int x=230, y=230;
static boolean coin1=true;
static int coinsCollected=0;
static int mj;
static boolean bounce=true;
public FinalGame() {
setSize(new Dimension(500, 500));
setBackground(Color.black);
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
moveSquare(e);
}
});
}
public void paint(Graphics g)
{
//refers to coin's coordinates
int c1x=20; int c1y=20;
g.setColor(Color.white);
g.fillRect(x,y,20,20);
g.setColor(Color.yellow);
g.fillOval(c1x, c1y, 20, 20);
if((x==c1x)&&(c1y==20))
{
coin1=false;
}
if(coin1==false)
{
g.setColor(Color.black);
g.fillOval(20, 20, 20, 20);
int j=230;
mj=5;
//I am unable to move the square while this loop is active
while(bounce)
{
repaint();
if((j==480)||(j==0))
{
mj=-mj;
}
j=j+mj;
g.setColor(Color.red);
g.fillRect(230, j, 20, 20);
delay();
g.setColor(Color.black);
g.fillRect(230, j, 20, 20);
g.setColor(Color.white);
g.fillRect(x,y,20,20);
}
mj=-mj;
}
g.setColor(Color.white);
g.fillRect(x,y,20,20);
}
public void moveSquare(KeyEvent e)
{
switch(e.getKeyCode())
{
case KeyEvent.VK_DOWN:
y += 5;
break;
case KeyEvent.VK_UP:
y-= 5;
break;
case KeyEvent.VK_LEFT:
x-=5;
break;
case KeyEvent.VK_RIGHT:
x+=5;
break;
}
repaint();
}
public static void main(String[] args)
{
JFrame frame = new JFrame("Basic Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FinalGame ex = new FinalGame();
frame.getContentPane().add(ex);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
ex.requestFocus();
}
public void delay()
{
try
{
Thread.sleep(15);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
Your algorithm is as follows:
create coins at random
move the player to collect the coins
create red things also at random
all these simultaneously.
Therefore you need different threads to enforce this simultaneity.
One thread for the coins one thread for the red things and one the main thread which already exists in the main class:
class FinalGame extends Canvas
{
private static final long serialVersionUID =1L;
//refers to players coordinates
static int x=230, y=230;
static boolean coin1=true;
static int coinsCollected=0;
static int mj;
static boolean bounce=true;
Red r;
Coin c;
public FinalGame() {
setSize(new Dimension(500, 500));
setBackground(Color.black);
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
moveSquare(e);
}
});
r=new Red(this);
r.start();
c=new Coin(this);
c.start();
}
public void paint(Graphics g)
{
if(x==r.x && y==r.y) System.exit(0);
if(c.visible) {
g.setColor(Color.yellow);
g.fillOval(c.c1x, c.c1y, 20, 20);
}
g.setColor(Color.white);
g.fillRect(x,y,20,20);
g.setColor(Color.red);
g.fillRect(r.x, r.y, 20, 20);
}
public void moveSquare(KeyEvent e)
{
switch(e.getKeyCode())
{
case KeyEvent.VK_DOWN:
y += 5;
break;
case KeyEvent.VK_UP:
y-= 5;
break;
case KeyEvent.VK_LEFT:
x-=5;
break;
case KeyEvent.VK_RIGHT:
x+=5;
break;
}
repaint();
}
public void m()
{
JFrame frame = new JFrame("Basic Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(this);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
requestFocus();
}
class Coin extends Thread {
int c1x=20, c1y=20;
boolean visible=true;
FinalGame f;
public Coin(FinalGame f) {
this.f=f;
}
public void run() {
while(true)
{
if((f.x==c1x)&&(c1y==20))
{
visible=false;
}
}
}
}
class Red extends Thread {
int x=130, y=10;
FinalGame f;
public Red(FinalGame f) {
this.f=f;
}
public void run() {
int mj=5;
while(true)
{
if((y==480)||(y==0))
{
mj=-mj;
}
y=y+mj;
f.repaint();
try
{
Thread.sleep(15);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
After execution, the loop completes its circles and then the repaint method is being called,
Is there an alternative way of drawing the image?
public class GameCanvas extends JPanel implements KeyListener {
private Tank tank1;
private Tank tank2;
private Rocket rocket;
public Graphics2D g2;
private Image img;
public boolean fire;
public GameCanvas() {
tank1 = new Tank(0, 0);
tank2 = new Tank(500, 500);
rocket = new Rocket(50, tank1);
init();
fire = false;
}
public void init() {
JFrame frame = new JFrame("Topak Tank");
frame.setLayout(new FlowLayout());
frame.setSize(1300, 740);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
this.setPreferredSize(new Dimension(1300, 740));
frame.add(this);
frame.addKeyListener(tank1);
frame.addKeyListener(this);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
tank1.draw(g);
// rocket.draw(g);
g2 = (Graphics2D) g;
if (fire == true) {
try {
img = ImageIO.read(getClass().getResource("rocket.png"));
System.out.println(rocket.getYPos());
g2.drawImage(img, rocket.getXPos(), rocket.getYPos(), null);
} catch (Exception e) {
}
}
repaint();
}
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_F: {
try {
int xPos = tank1.getXAxis();
int yPos = tank1.getYAxis();
fire = true;
int delay = 10000;
// img = ImageIO.read(getClass().getResource("rocket.png"));
int count = 0;
while (true) {
System.out.println(xPos);
System.out.println(yPos);
if (count == 5) {
break;
}
count++;
// g2.drawImage(img,xPos,yPos,null);
rocket.setYPos(yPos);
System.out.println("loop");
Timer t = new Timer(delay, null);
t.start();
yPos++;
this.repaint();// here i want to excute and draw image after every lop cycle
Thread.sleep(100);
}
System.out.println("Fired");
fire = false;
} catch (Exception io) {
JOptionPane.showMessageDialog(null, "Could not found Rocket image");
}
}
break;
}
}
public void keyReleased(KeyEvent ke) {
}
public void keyTyped(KeyEvent ke) {
}
public static void main(String[] arg) {
GameCanvas gc = new GameCanvas();
}
}
Calling repaint() just tells the component to repaint itself whenever the EDT is available again. Since that entire loop is on the EDT, the component can't repaint itself until it's done.
You should probably be using a Timer or a Thread instead of tying up the EDT with that loop. You should NOT be calling sleep() on the EDT.
More info here: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
I am learning Java game development and I am having an issue understanding why the "Robot" is not moving.
I know the issue is with the repaint but I can not figure it out.
please help
Thank
Game Class
public class GameMain extends Applet implements KeyListener {
private Image image, character;
private Graphics gpx;
private Droid droid;
private URL base;
private static Background bg1, bg2;
#Override
public void init() {
setSize(800, 480);
setBackground(Color.BLACK);
setFocusable(true);
addKeyListener(this);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("My First Game");
droid = new Droid();
base = getDocumentBase();
character = getImage(base, "data/char.png");
}
#Override
public void start() {
GameThread thread = new GameThread();
thread.start();
System.out.println("Thread Started");
}
#Override
public void stop() {
}
#Override
public void destroy() {
}
#Override
public void update(Graphics g) {
if(image == null){
image = createImage(this.getWidth(), this.getHeight());
gpx = image.getGraphics();
}
gpx.setColor(getBackground());
gpx.fillRect(0, 0, getWidth(), getHeight());
gpx.setColor(getForeground());
paint(gpx);
g.drawImage(image, 0, 0, this);
}
#Override
public void paint(Graphics g) {
g.drawImage(character, droid.getPositionX() - 61, droid.getPositionY()- 63, this);
}
#Override
public void keyPressed(KeyEvent key) {
switch(key.getKeyCode() ){
case KeyEvent.VK_UP:
break;
case KeyEvent.VK_DOWN:
break;
case KeyEvent.VK_LEFT:
droid.moveLeft();
break;
case KeyEvent.VK_RIGHT:
droid.moveRight();
break;
case KeyEvent.VK_SPACE:
droid.jump();
break;
}
}
#Override
public void keyReleased(KeyEvent key) {
switch(key.getKeyCode() ){
case KeyEvent.VK_UP:
break;
case KeyEvent.VK_DOWN:
break;
case KeyEvent.VK_LEFT:
droid.stop();
break;
case KeyEvent.VK_RIGHT:
droid.stop();
break;
case KeyEvent.VK_SPACE:
break;
}
}
#Override
public void keyTyped(KeyEvent key) {
// TODO Auto-generated method stub
}
}
Thread Class
public class GameThread extends Thread {
GameMain game;
Droid droid;
private static Background bg1, bg2;
public GameThread(){
bg1 = new Background(0,0);
bg2 = new Background(2160, 0);
}
#Override
public void run() {
game = new GameMain();
droid = new Droid();
//Game while loop
while(true){
droid.update();
game.repaint();
//bg1.update();
//bg2.update();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Droid Class
public class Droid {
private int positionX = 100;
private int positionY = 382;
private int speedX = 0;
private int speedY = 1;
private boolean jump = false;
public void update(){
//Update X Position
if(speedX < 0){
positionX += speedX;
}else if(speedX == 0){
System.out.println("Do not scroll the background.");
}else{
if(positionX <= 150){
positionX += speedX;
}else{
System.out.println("Scroll Background Here");
}
}
//Update Y Position
if(positionY + speedY >= 382){
positionY = 382;
}else{
positionY += speedY;
}
//update Jump
if(jump == true){
speedY += 1;
if(positionY + speedY >= 382){
positionY = 382;
speedY = 0;
jump = false;
}
}
}
public void moveRight(){
speedX = 6;
System.out.println(speedX);
}
public void moveLeft(){
speedX = -6;
System.out.println(speedX);
}
public void stop(){
speedX = 0;
}
public void jump(){
if(jump == false){
speedY = -15;
jump = true;
}
}
public void setPositionX(int positionX){
this.positionX = positionX;
}
public int getPositionX(){
return positionX;
}
public void setPositionY(int positionY){
this.positionY = positionY;
}
public int getPositionY(){
return positionY;
}
public void setSpeedX(int speedX){
this.speedX = speedX;
}
public int getSpeedX(){
return speedX;
}
public void setSpeedY(int speedY){
this.speedY = speedY;
}
public int getSpeedY(){
return speedY;
}
}
The problem is, the droid you're updating isn't the droid you're painting...in fact, the GameMain you're repainting isn't the one that is one the screen...
public class GameMain extends Applet implements KeyListener {
//...
private Droid droid;
//...
#Override
public void init() {
//...
droid = new Droid();
//...
}
#Override
public void paint(Graphics g) {
g.drawImage(character, droid.getPositionX() - 61, droid.getPositionY()- 63, this);
}
And then in you GameThread;
public class GameThread extends Thread {
GameMain game;
Droid droid;
//...
#Override
public void run() {
// Created a new GameMain
game = new GameMain();
// Created a new Droid...
droid = new Droid();
//Game while loop
while (true) {
droid.update();
game.repaint();
//...
You create new instances of GameMain and Droid, these have no connection what so ever to the screen.
Instead, you should be passing a reference of GameMain to the GameThread and GameThread should be telling GameMain to update the game state...
For example...
Add the method updateGameState
public class GameMain extends Applet implements KeyListener {
//...
public void updateGameState() {
droid.update();
repaint();
}
//...
Then in GameMain's start method, pass a reference of GameMain to GameThread...
GameThread thread = new GameThread(this);
thread.start();
Then in GameMain, store the reference you are passed and remove any reference to Droid
public class GameThread extends Thread {
//...
private GameMain gameMain;
public GameThread(GameMain gameMain) {
this.gameMain = gameMain;
//...
Then in GameTread#run, call gameMain.updateGameState();...
public void run() {
while (true) {
gameMain.updateGameState();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
As a side note...
Applet is outdated, you should be using JApplet
I'd be very careful using this.getParent().getParent(), you may not like the results if you deployed this in a browser..
And when you start using JApplet, move you game rendering to something like JPanel, overriding it's paintComponent method, this will give you automatic double buffering and use the Key binding API over KeyListener. It's more easily, programmatically, updatable and doesn't suffer from the same focus related issues as KeyListener
I'm just starting out trying to make games and I did a HelloWorld Applet, then tested my idea for scrolling on it, and eventually it started turning into a "helicopter" style game. Now everything worked fine until I decided to put a bunch of switch statements in to handle states(title screen, running, and game over). The code that was functioning before is unchanged, and my new "intro screen" works fine, but when you switch into the game state the double buffering seems to go out of whack. The game foreground flashes on and off quickly and has triangles cut out of it, and the background hardly renders at all. This is just me exploring basic principles of game coding, so it's not elegant or modular or anything, but it should work...
[EDIT] I know that Applets and AWT in general is probably a bad way to go, but I started it like this and I just want to learn how this works and what I'm doing wrong so I can be satisfied and move on.
package testStuff;
import java.awt.*;
import java.applet.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class HelloWorld extends Applet implements Runnable{
//game time counter
int count = 0;
//controller object
Controller control;
//accesses images and creates image variables
File wavesource = new File("C:\\sourceimages\\waves.jpg");
File playerSource = new File("C:\\sourceimages\\plane3.png");
Image player = null;
Image waves = null;
//font for score
Font myFont;
//double buffer objects
Graphics bground;
Image bgImage = null;
private int bgx = 0;
//player position
private int xPos=0;
private int yPos=50;
//arrays for tunnel locations
private int[] topTunnel = new int[200];
private int[] botTunnel = new int[200];
//size of tunnel
private int tunnelSize;
//boolean determines direction of tunnel movement
private boolean tunUp;
//state
private int state;
//"constructor"
public void init(){
//set state
state = 0;
//instantiates controller adds it to the applet
control = new Controller();
this.addKeyListener(control);
//instantiates images
try {
waves = ImageIO.read(wavesource);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
player = ImageIO.read(playerSource);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//instantiates arrays and tunnel size
for(int i=0;i<199;i++){
topTunnel[i]=-1;
botTunnel[i]=-1;
}
topTunnel[199]=20;
botTunnel[199]=179;
tunnelSize = botTunnel[199]-topTunnel[199];
tunUp = false;
}
public void paint(Graphics g){
switch(state){
case 0:
g.setColor(Color.black);
myFont = new Font("Courier", Font.BOLD+Font.ITALIC, 12);
g.setFont(myFont);
g.drawString("DON'T CRASH THE PLANE BRO", 10, 100);
myFont = new Font("Courier", Font.PLAIN, 8);
g.setFont(myFont);
g.drawString("Press Spacebar to Play", 40, 150);
break;
case 1:
g.drawImage(player, xPos, yPos, null);
g.setColor(Color.red);
for(int i=0;i<200;i++){
g.fillRect(i, 0, 1, topTunnel[i]);
g.fillRect(i, botTunnel[i], 1, botTunnel[i]);
}
g.setColor(Color.cyan);
myFont = new Font("Helvetica", Font.PLAIN, 12);
setFont(myFont);
if(count<170)
g.drawString("SCORE: " + 0, 0, 12);
else
g.drawString("SCORE: " + (this.count-170), 0, 12);
break;
}
}
public void start(){
Thread thread = new Thread(this);
thread.start();
}
#Override
public void run(){
while(true){
switch(state){
case 0:
//increases count
count++;
//paints
this.repaint();
try {
Thread.sleep(1000/30);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(control.spaceDown()){
state = 1;
count = 0;
}
break;
case 1:
//increases count
count++;
//handles scrolling
if(xPos<75){
xPos++;
}
else{
if(bgx>-600){
bgx--;
}
else{
bgx=0;
}
}
//handles input
if(control.spaceDown()==true&&yPos>=0){
yPos--;
}
else if(yPos<180){
yPos++;
}
//repositions tunnel
if(xPos>=75){
for(int i=1;i<200;i++){
topTunnel[i-1]=topTunnel[i];
botTunnel[i-1]=botTunnel[i];
}
}
//defines new tunnel space
if(topTunnel[199]<=0 || !tunUp)
topTunnel[199]++;
if(botTunnel[199]>=200 || tunUp)
topTunnel[199]--;
botTunnel[199] = topTunnel[199]+tunnelSize;
//randomly chooses direction to move tunnel
double randomNum = Math.random();
if(randomNum>.5)
tunUp = true;
else
tunUp = false;
//narrows tunnel
if(count%20 == 0)
tunnelSize--;
//calls update
this.repaint();
//handles framerate
try {
Thread.sleep(1000/30);
} catch (InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
public void update(Graphics g){
//instantiates image and graphics on first tick
if(bgImage == null){
bgImage = createImage(this.getSize().width, this.getSize().height);
bground = bgImage.getGraphics();
}
//create background based on state
switch(state){
case 0:
//flashing colors!
if(count%20<10){
bground.setColor(Color.yellow);
bground.fillRect(0, 0, 200, 200);
}
else{
bground.setColor(Color.orange);
bground.fillRect(0, 0, 200, 200);
}
break;
case 1:
//draws background image(s)
bground.drawImage(waves,bgx,0,this);
if(bgx<-399)
bground.drawImage(waves,bgx+600,0,this);
break;
}
//paint over the background then draw it to screen
paint(bground);
g.drawImage(bgImage, 0, 0, this);
}
}
You need to "clear" the graphics on each frame, otherwise you are painting on what was previously painted...
In the example below, I've filled the graphics context while it's "playing", but left as is when it's paused, you should be able to see the difference...
public class HelloWorld extends Applet implements Runnable {
private int direction = 4;
private int state = 0;
private Image bgImage;
private Graphics bground;
private int count;
private int x = 0;
//"constructor"
public void init() {
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
if (state == 0) {
state = 1;
} else if (state == 1) {
state = 0;
}
}
}
});
}
public void paint(Graphics g) {
switch (state) {
case 0:
g.setColor(Color.black);
g.drawString("DON'T CRASH THE PLANE BRO", 10, 100);
g.drawString("Press Spacebar to Play", 40, 150);
break;
case 1:
break;
}
}
public void start() {
Thread thread = new Thread(this);
thread.start();
}
#Override
public void run() {
while (true) {
switch (state) {
case 0:
count++;
this.repaint();
break;
case 1:
x += direction;
if (x < 0) {
x = 0;
direction *= -1;
} else if (x > getWidth()) {
x = getWidth();
direction *= -1;
}
//calls update
this.repaint();
//handles framerate
try {
Thread.sleep(1000 / 30);
} catch (InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
public void update(Graphics g) {
//instantiates image and graphics on first tick
if (bgImage == null) {
bgImage = createImage(this.getSize().width, this.getSize().height);
bground = bgImage.getGraphics();
}
//create background based on state
switch (state) {
case 0:
//flashing colors!
if (count % 20 < 10) {
bground.setColor(Color.yellow);
bground.fillRect(0, 0, 200, 200);
} else {
bground.setColor(Color.orange);
bground.fillRect(0, 0, 200, 200);
}
break;
case 1:
bground.setColor(Color.WHITE);
bground.fillRect(0, 0, getWidth(), getHeight());
bground.setColor(Color.RED);
int y = (getHeight() / 2) - 4;
bground.fillOval(x, y, 8, 8);
break;
}
//paint over the background then draw it to screen
paint(bground);
g.drawImage(bgImage, 0, 0, this);
}
}
I think you should start but adding more braces. I'm a beginner at coding but from what I've been reading, coding lengthy statements without braces on certain statements in your code would result in some errors.
There are a lot of processes going on here and I feel like braces help a
//defines new tunnel space
if(topTunnel[199]<=0 || !tunUp)
topTunnel[199]++;
if(botTunnel[199]>=200 || tunUp)
topTunnel[199]--;
botTunnel[199] = topTunnel[199]+tunnelSize;
//randomly chooses direction to move tunnel
double randomNum = Math.random();
if(randomNum>.5)
tunUp = true;
else
tunUp = false;
//narrows tunnel
if(count%20 == 0)
tunnelSize--;
//calls update
this.repaint();
Correct me if I'm wrong, I just want to learn too!
How do I use KeyListener on this code to move up and down? Ii know how to use KeyListener but I don't know where it put it on this code.
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
public class ControlPanel extends JPanel implements Runnable,ActionListener,KeyListener,MouseListener{
private MainPanel main;
private final static int maxWidth = 800, maxHeight = 600; //width & height of JPanel
private boolean running; //keeps track of state of the program
private Thread thread;
private Graphics2D graphics;
private Image image; //used for double buffering
private BufferedImage bgImage;
private String s = "";
Font f = new Font("Times New Roman",Font.PLAIN,50);
Timer t = new Timer(2000,this);
private int typed = 0;
private int x = 50,y = 500;
public ControlPanel(MainPanel main) {
this.setDoubleBuffered(false); //we'll use our own double buffering method
this.setBackground(Color.black);
this.setPreferredSize(new Dimension(maxWidth, maxHeight));
this.setFocusable(true);
this.requestFocus();
this.main = main;
addKeyListener(this);
addMouseListener(this);
t.start();
}
public static void main(String[] args) {
new MainPanel();
}
public void addNotify() {
super.addNotify();
startGame();
}
public void stopGame() {
running = false;
}
//Creates a thread and starts it
public void startGame() {
if (thread == null || !running) {
thread = new Thread(this);
}
thread.start(); //calls run()
}
public void run() {
running = true;
init();
while (running) {
createImage(); //creates image for double buffering
///////////////USE THESE 2 METHODS////////////////////
update(); //use this to change coordinates, update values, etc
draw(); //use this to draw to the screen
//////////////////////////////////////////////////////
drawImage(); //draws on the JPanel
}
System.exit(0);
}
//Use this to create or initialize any variables or objects you have
public void init() {
}
public void initGame(){
}
//Use this to update anything you need to update
public void update() {
}
//Use this to draw anything you need to draw
public void draw() {
graphics.setColor(Color.WHITE);
graphics.fillRect(250, 450, 300,100);
graphics.setColor(Color.WHITE);
graphics.fillRect(250, 320, 300,100);
graphics.setColor(Color.GREEN);
graphics.setFont(f);
graphics.drawString(s, x, y);
typed = 0;
graphics.setFont(f);
graphics.setColor(Color.blue);
graphics.drawString("HANGMAN", 270,75);
graphics.setFont(f);
graphics.setColor(Color.blue);
graphics.drawString("PLAY", 330, 390);
graphics.setFont(f);
graphics.setColor(Color.blue);
graphics.drawString("QUIT", 330, 520);
graphics.setColor(Color.red);
graphics.drawRect(248, 318, 304,104);
}
//creates an image for double buffering
public void createImage() {
if (image == null) {
image = createImage(maxWidth, maxHeight);
if (image == null) {
System.out.println("Cannot create buffer");
return;
}
else
graphics = (Graphics2D)image.getGraphics(); //get graphics object from Image
}
if (bgImage == null) {
graphics.setColor(Color.black);
graphics.fillRect(0, 0, maxWidth, maxHeight);
//System.out.println("No background image");
}
else {
//draws a background image on the Image
graphics.drawImage(bgImage, 0, 0, null);
}
}
//outputs everything to the JPanel
public void drawImage() {
Graphics g;
try {
g = this.getGraphics(); //a new image is created for each frame, this gets the graphics for that image so we can draw on it
if (g != null && image != null) {
g.drawImage(image, 0, 0, null);
g.dispose(); //not associated with swing, so we have to free memory ourselves (not done by the JVM)
}
image = null;
}catch(Exception e) {System.out.println("Graphics objects error");}
}
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
typed = 1;
s+=Character.toString(e.getKeyChar());
s+=" ";
System.out.println(s);
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(e.getPoint());
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
KeyListener isn‘t designated for listening of keyboard events for Swing JComponents, use KeyBindings instead, output to the Swing GUI should be from Swing Action
You have added key listener by calling this
addKeyListener(this);