Im not sure if this problem has come up with anyone else, but Im doing some simple animation things. Im trying to have a transparent background, which has been easy to make with the following code:
jf.setBackground(new Color(0,0,0,0));
The problem is, whenever the thing im trying to move moves(a shrek picture in my case), it constantly paints and isnt clearing the previous shreks. Ill post all my code down below.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.io.*;
import java.util.logging.*;
import java.util.logging.*;
import javax.imageio.*;
public class MoveTest extends JPanel implements KeyListener {
double velX = 0;
double velY = 0;
double moveX = 0;
double moveY = 0;
double posX = 1;
double posY = 1;
double friction = 1.005;
BufferedImage image;
public void paintComponent(Graphics g) {
super.paintComponent(g);
try{
image = ImageIO.read(new File("shrek.png"));
}catch (IOException ex){
System.out.println("Image Does Not Exist");
}
g.setColor(Color.RED);
moveX += velX;
moveY += velY;
posX += moveX;
posY += moveY;
g.drawImage(image,(int)posX,(int)posY,null);
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
int up = KeyEvent.VK_UP, w = KeyEvent.VK_W;
int down = KeyEvent.VK_DOWN, s = KeyEvent.VK_S;
int left = KeyEvent.VK_LEFT, a = KeyEvent.VK_A;
int right = KeyEvent.VK_RIGHT, d = KeyEvent.VK_D;
if(key == w || key == up)
velY = -.2;
if(key == s || key == down)
velY = .2;
if(key == a || key == left)
velX = -.2;
if(key == d || key == right)
velX = .2;
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
int up = KeyEvent.VK_UP, w = KeyEvent.VK_W;
int down = KeyEvent.VK_DOWN, s = KeyEvent.VK_S;
int left = KeyEvent.VK_LEFT, a = KeyEvent.VK_A;
int right = KeyEvent.VK_RIGHT, d = KeyEvent.VK_D;
if(key == w || key == up)
velY = 0;
if(key == s || key == down)
velY = 0;
if(key == a || key == left)
velX = 0;
if(key == d || key == right)
velX = 0;
}
public void keyTyped(KeyEvent e){}
public static void main(String[] args) {
MoveTest mt = new MoveTest();
JFrame jf = new JFrame();
jf.setTitle("Test one cladss");
jf.setSize(1440,900);
jf.setBackground(new Color(0,0,0,0));
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(mt);
jf.setVisible(true);
mt.setOpaque(true);
mt.addKeyListener(mt);
mt.requestFocusInWindow();
while(true){
//jf.removeAll();
jf.repaint();
mt.collision();
mt.friction();
try {
Thread.sleep(16);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
public void collision(){
if(posX >= 1440-50|| posX <= 0){
velX -= (2*velX);
moveX -= (2*moveX);
}
if(posY >= 900-50 || posY <= 0){
velY -= (2*velY);
moveY -= (2*moveY);
}
}
public void friction(){
moveX /= friction;
moveY /= friction;
}
}
If you anything more information please comment it. Any help is appreciated!
I have run into this before. The paintComponent method overridden from a JFrame is different than overriding from all other components. Since you have overriden the JFrame's paint code, it is no longer erasing the background. There are two solution:
Add your own JComponent (JPanel would work well) and override it's paint methods instead of the JFrames.
or
Clear the canvas yourself as the first thing you do after you call super.paintComponent.
In Addition:
You should not be reading your image every time you paint. Since painting happens soon after repaint is called from any thread, the image could load many many times. If you need to load it once, create a nameless instance block in the class like so:
{
try{
image = ImageIO.read(new File("shrek.png"));
}catch (IOException ex){
System.out.println("Image Does Not Exist");
}
}
If you are only ever going to have one copy, make it a static block:
static {
<load image here>
}
If you want to reload the image every frame because it changes you need to find a way not to do that. Instead any image animation should happen by editing the BufferImage object in java or loading a sprite-map.
Related
I'm currently trying to make a reset button for my java platformer game using the enter key from the keyboard. The way that my level loads is as a BufferedImage object passed through a method I named LoadImageLevel. What I have tried to do is simply say
if(key == KeyEvent.VK_ENTER){ LoadImageLevel(level)}
where level is my BufferedImage object storing the level. This does reset the level upon pressing the key, but once the level is reset a few times the game gets ridiculously slow and the character can't move because it is so slow.
I'm thinking this is because every time I reset the level it just puts the images on top of each other until it's doing too much at once so it slows up the game.
I've been looking around to see if there is a way to clear out the previous BufferedImages each time I reset the level so that it only runs 1 image at a time thus keeping the game up to speed... I hope. Unfortunately there is no clear() or remove() method in the BufferedImage class and I have not been able to make one.
Any help will be appreciated, thanks!
package com.tim.neon.window;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
//import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.Random;
//import com.tim.neon.framework.GameObject;
import com.tim.neon.framework.KeyInput;
import com.tim.neon.framework.ObjectId;
import com.tim.neon.objects.Block;
import com.tim.neon.objects.Player;
//Developed by Timothy O'Leary with much help from RealTutsGML
public class Game extends Canvas implements Runnable {
/**
*
*/
private static final long serialVersionUID = 5023365827045558937L;
private boolean running = false;
private Thread thread;
public static int WIDTH, HEIGHT;
private BufferedImage level = null;
Handler handler;
Camera cam;
Random rand = new Random();
private void init(){
WIDTH = getWidth();
HEIGHT = getHeight();
BufferedImageLoader loader = new BufferedImageLoader();
level = loader.loadImage("/level2.png");//loading the level
handler = new Handler();
cam = new Camera(0, 0);
LoadImageLevel(level);
this.addKeyListener(new KeyInput(handler));
}
public synchronized void start(){
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
public void run(){
init(); //
this.requestFocus(); //
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int updates = 0;
int frames = 0;
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
tick();
updates++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000){
timer += 1000;
System.out.println("FPS: " + frames + " Ticks: " + updates);
frames = 0;
updates = 0;
}
}
}
private void tick(){
handler.tick();
for(int i = 0; i < handler.object.size(); i++){
if(handler.object.get(i).getId() == ObjectId.Player){
cam.tick(handler.object.get(i));
}
}
}
private void render(){
BufferStrategy bs = this.getBufferStrategy();
if(bs == null){
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
Graphics2D g2d = (Graphics2D) g;
//////////////////////////
//draw here
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
g2d.translate(cam.getX(), cam.getY());//begin of cam
handler.render(g);
g2d.translate(-cam.getX(), -cam.getY());//end of cam
/////////////////////////
g.dispose();
bs.show();
}
private void LoadImageLevel(BufferedImage image){//function to load levels drawn pixel by pixel in paint
int w = image.getWidth();
int h = image.getHeight();
System.out.println("width, height:" + " " + w + " " + h);
for(int xx = 0; xx < h; xx++){
for(int yy = 0; yy < w; yy++){
int pixel = image.getRGB(xx, yy);
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
if(red == 255 && green == 255 && blue == 255) handler.addObject(new Block(xx*32, yy*32, ObjectId.Block));
if(red == 0 && green == 0 && blue == 255) handler.addObject(new Player(xx*32, yy*32,handler, ObjectId.Player));
}
}
}
public static void main(String args[]){
new Window(800, 600, "Neon Platform Game Prototype", new Game());
}
}
package com.tim.neon.framework;
import java.awt.Component;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import com.tim.neon.objects.Block;
import com.tim.neon.objects.Player;
import com.tim.neon.window.BufferedImageLoader;
import com.tim.neon.window.Game;
import com.tim.neon.window.BufferedImageLoader;
import com.tim.neon.window.Handler;
import com.tim.neon.window.Game;
import com.tim.neon.window.Window;
public class KeyInput extends KeyAdapter {
Handler handler;
//public BufferedImage level = null;//i added
public KeyInput(Handler handler){
this.handler = handler;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
//BufferedImageLoader loader = new BufferedImageLoader();///
//level = loader.loadImage("/level2.png");//loading the level///
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ObjectId.Player){
if(key == KeyEvent.VK_D) tempObject.setVelX(5);
if(key == KeyEvent.VK_A) tempObject.setVelX(-5);
if(key == KeyEvent.VK_SPACE && !tempObject.isJumping()){//for double jump do if(key == KeyEvent.VK.SPACE) tempObject.setVelY(-15)
tempObject.setJumping(true);
tempObject.setVelY(-15);//change number to increase or decrease jump height
}
}
}
if(key == KeyEvent.VK_ESCAPE){
System.exit(1);
}
//if(key == KeyEvent.VK_ENTER){/// trying to make reset button
// level.repaint();
//}///
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ObjectId.Player){
if(key == KeyEvent.VK_D) tempObject.setVelX(0);
if(key == KeyEvent.VK_A) tempObject.setVelX(0);
}
}
}
/*private void LoadImageLevel(BufferedImage image){// this function is used in both this clas and the Game class
int w = image.getWidth();
int h = image.getHeight();
System.out.println("width, height:" + " " + w + " " + h);
for(int xx = 0; xx < h; xx++){
for(int yy = 0; yy < w; yy++){
int pixel = image.getRGB(xx, yy);
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
if(red == 255 && green == 255 && blue == 255) handler.addObject(new Block(xx*32, yy*32, ObjectId.Block));
if(red == 0 && green == 0 && blue == 255) handler.addObject(new Player(xx*32, yy*32,handler, ObjectId.Player));
}
}
}*/
}
I have a program to move a square about using the keyboard. It moves around fine when I press one of the arrow keys, but if I move it to the edge of the frame, I want it to stop. It does not do this however. If I move the square to the edge of the frame it keeps going and moves right past the edge of the screen.
I have put controls into my code to try stopping the square, but they don't seem to be working. Not really sure what is going wrong here.
This is the code to set up and draw the square:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
#SuppressWarnings("serial")
public class MovingSquare extends JPanel implements ActionListener, KeyListener
{
// We need a timer to move the shape
Timer shapeTimer = new Timer(5, this);
// X and Y coordinates of square (top left corner), and the factors by which it will move or resize each time
double xPos = 0, yPos = 0, movementX = 0, movementY = 0;
// Size of the square
int squareSize = 40;
// Width and height of the parent frame
int windowWidth;
int windowHeight;
// Movement bounds of the square
// These will prevent it from being moved off the edge of the frame
int xBound;
int yBound;
// Constructor method for our class
public MovingSquare(int w, int h) // Constructor is passed the size of the parent frame
{
// Start the timer
shapeTimer.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
windowWidth = w;
windowHeight = h;
xBound = (windowWidth - squareSize);
yBound = (windowHeight - squareSize);
}
// This is where the fun starts! Painting the graphics object
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// Create a new rectangle (which is actually a square!)
Rectangle2D movableSquare = new Rectangle2D.Double(xPos, yPos, squareSize, squareSize);
// Draw the above square on the graphics object
g2.draw(movableSquare);
}
public void actionPerformed(ActionEvent e)
{
// Redraw the square when something happens
repaint();
// Set the new x and y coordinates, depending on which direction we have moved
xPos += movementX;
yPos += movementY;
}
public void moveUp()
{
// Check to see if the shape is already at the top edge of the screen
if (yPos == 0)
{
movementY = 0;
movementX = 0;
}
// Set the movement factor - negative Y because we are moving UP!
movementY = -0.5;
movementX = 0;
}
public void moveDown()
{
// Check to see if the shape is already at the bottom edge of the screen - specified by the X and Y bounds
if (yPos == yBound)
{
movementY = 0;
movementX = 0;
}
// Set the movement factor - positive Y because we are moving DOWN!
movementY = 0.5;
movementX = 0;
}
public void moveLeft()
{
// Check to see if the shape is already at the left hand edge of the screen
if (xPos == 0)
{
movementY = 0;
movementX = 0;
}
// Set the movement factor - negative X because we are moving LEFT!
movementX = -0.5;
movementY = 0;
}
public void moveRight()
{
// Check to see if the shape is already at the right hand edge of the screen - specified by the X and Y bounds
if (xPos == xBound)
{
movementY = 0;
movementX = 0;
}
// Set the movement factor - positive X because we are moving RIGHT!
movementX = 0.5;
movementY = 0;
}
public void enlargeSquare()
{
// Make the square larger
squareSize++;
}
public void shrinkSquare()
{
// Make the square smaller
squareSize--;
}
public void keyPressed(KeyEvent e)
{
// Get the Key Code of the key that has been pressed
int keyCode = e.getKeyCode();
// If the up key has been pressed
if (keyCode == KeyEvent.VK_UP)
{
// Move shape up
moveUp();
}
// If the down key has been pressed
if (keyCode == KeyEvent.VK_DOWN)
{
// Move shape down
moveDown();
}
// If the right key is pressed
if (keyCode == KeyEvent.VK_RIGHT)
{
// Move shape right
moveRight();
}
// If the left key is pressed
if (keyCode == KeyEvent.VK_LEFT)
{
// Move shape left
moveLeft();
}
// If the left brace key is pressed
if (keyCode == KeyEvent.VK_OPEN_BRACKET)
{
shrinkSquare();
}
// If the right brace key is pressed
if (keyCode == KeyEvent.VK_CLOSE_BRACKET)
{
enlargeSquare();
}
}
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
// Get the Key Code of the key that has been released
int keyCode = e.getKeyCode();
// If the down key was released
if (keyCode == KeyEvent.VK_UP)
{
movementX = 0;
movementY = 0;
}
// If the down key was released
if (keyCode == KeyEvent.VK_DOWN)
{
movementX = 0;
movementY = 0;
}
// If the right key was released
if (keyCode == KeyEvent.VK_RIGHT)
{
movementX = 0;
movementY = 0;
}
// If the left key was released
if (keyCode == KeyEvent.VK_UP)
{
movementX = 0;
movementY = 0;
}
}
}
And this is the main class:
import javax.swing.JFrame;
public class Square
{
public static void main(String args[])
{
// Set width and height of frame
int frameWidth = 1024;
int frameHeight = 768;
// Create new frame and set size
JFrame frmMain = new JFrame();
frmMain.setSize(frameWidth, frameHeight);
// Create a moving square and add to the frame
MovingSquare mySquare = new MovingSquare(frameWidth, frameHeight);
frmMain.add(mySquare);
// Final configuration settings for frame.
frmMain.setVisible(true);
frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmMain.setTitle("Moving Square");
}
}
You actionPerformed method is updating the position of your square, well beyond what your moveXxx methods are, you should do your range checking there
#Override
public void actionPerformed(ActionEvent e)
{
// Set the new x and y coordinates, depending on which direction we have moved
xPos += movementX;
yPos += movementY;
if (xPos < 0) {
xPos = 0;
} else if (xPos + squareSize > xBound) {
xPos = xBound - squareSize;
}
if (yPos < 0) {
yPos = 0;
} else if (yPos + squareSize > yBound) {
yPos = yBound - squareSize;
}
// Redraw the square when something happens
repaint();
}
If you know the width and height of ths screen and the rect, you can easiely check if it's inside:
int fX0 = 0, // left x border
fX1 = frameWidth, // right x border
fY0 = 0, // top y border
fY1 = frameHeight; // bottom y border
int rX0, rX1, rY0, rY1; // keep these values updated width the rectangles position:
//rX0 = rectangle position x
//rX1 = rectangle position x + rectangle width
//rY0 = rectangle position y
//rY1 = rectangle position y + rectangle height
// Then, to check if the rect is inside the frame:
if (
rX0 >= fX0 &&
rX1 < fX1 &&
rY0 >= fY0 &&
rY1 < fY1
) { /* the rectangle is inside the frame bounds */ }
else { /* it's not inside the bounds, e.g. cancel movement */ }
The second method of doing this is by using the Rectangle class (from awt I think):
Rectangle f = new Rectangle(0, 0, frameWidth, frameHeight); // bounds of the frame
Rectangle r = new Rectangle(...); // Your square bounds
// To check if r is inside f
if (
f.contains(r)
) { /* the rectangle is inside the frame bounds */ }
else { /* it's not inside the bounds, e.g. cancel movement */ }
You can make an extra method:
public boolean Check(){
if(xPos >0 && xPos-squareSize<frameWidth && yPos>0 && yPos-squareSize<frameHeight){
//use a flag for example and make it false
}else
//flag==true
return flag;
}
Into KeyEvent method(if flag==true) then do the movement else do nothing or reset the xpos and ypos coordinates back to default or to a specific position of the JFrame.
Also it is easy to add an If(into KeyEvent methods)statement to check the coordinates and if they are accepted then do the movement.
For example:
public void KeyPressed(KeyEvent key){
if(Check()==true){
..........//the code you have into KeyPressed method
}
}//end of method KeyPressed
My "checkiftouching" method is not working. It is suppose to change the location of the circle and give you a point when the square and circle are touching. It senses when they are touching by checking when there locations are close enough together. The rest of the program runs smoothly. It has a square that moves with the arrows.
import java.awt.Graphics;
public class RunPaintGUI extends JFrame implements KeyListener{
int x = 30;
int y = 30;
Random randomgenerator = new Random();
int a = randomgenerator.nextInt(1220);
int b = randomgenerator.nextInt(700);
public static void main(String[] args){
RunPaintGUI RunPaintGUI = new RunPaintGUI();}
public RunPaintGUI(){
this.setSize(1275, 775);
this.setResizable(false);
this.setVisible(true);
this.setTitle("game")
this.addKeyListener(this);
}
public void paint(Graphics g){
super.paint(g);
g.fill3DRect(x,y, 60, 60, true);
g.fillOval(a, b, 50, 50);
g.drawString("score: " + score, 600, 50);
}
public void checkiftouching(){
if ((a - x) < 70){
if ((a -x) > -70){
if ((b - y) < 70){
if ((b - y) > -70){
System.out.println("you win");
a = randomgenerator.nextInt(1220);
b = randomgenerator.nextInt(720);
repaint();
score = score + 1;
}}}}}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT){
x = x - 10;
repaint();
else if (e.getKeyCode() == KeyEvent.VK_RIGHT){
x = x + 10;
repaint();
else if (e.getKeyCode() == KeyEvent.VK_UP){
y = y - 10;
repaint();
else if (e.getKeyCode() == KeyEvent.VK_Left){
y = y + 10;
repaint();
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e {
// TODO Auto-generated method stub
}
It sounds like you need a hitbox. A hitbox, which is commonly used in game to detect collisions, can be used in your scenario. A hitbox is simply a rectangle that you don't draw but still keep track of its position. You should use a Rectangle for a hitbox. If you would prefer to use a ellipse for your cirlces though you can use a Ellipse2D. Although if you do this you will have to use a Rectangle2D.
Rectangle hitbox = new Rectangle(x,y,width,height);
//...
if (e.getKeyCode() == KeyEvent.VK_LEFT){
x = x - 10;
hitbox.x = x;
repaint();
// and so on for your various key events
Your checkiftouching() method gets much simpler with hitboxes.
if (hitbox1.intersects(hitbox)) {
System.out.println("you win");
a = randomgenerator.nextInt(1220);
b = randomgenerator.nextInt(720);
repaint();
score = score + 1;
}
If you choose to use an Ellipse2D then you must declare it like this:
Ellipse2D.Double hitbox = new Ellipse2D.Double(x,y,width,height);
Then you set the x coordinate:
hitbox.setFrame(newXCoordinate, hitbox.getY(), hitbox.getWidth(), hitbox.getHeight());
Or the y coordinate:
hitbox.setFrame(hitbox.getX(), newYCoordinate, hitbox.getWidth(), hitbox.getHeight());
I am designing a simple java 2d game.where an aircraft shoots missiles and they hit alien ships.(pictures are attached for a better understanding).
Now I need to detect when the missile hits the alien ship. So as to count the number of total hits. I used the rectangle1.intersects(rec2)method, but instead of giving me an integer 1 as the answer (after the boolean of course) it gives me some funny answer. I guess like how much the two rectangles intersect...
Also when adding new aliens in an arraylist I use the following: I add new aliens every two seconds, but this slows down the game very much.
So please guide me on these two issues.
There is a game class (contains the main frame), board class (the panel on which I draw) alient, missile and craft class. Below I am giving the the actionPerformed() of the panel class which gets called by a timer every 2ms (the rest of the code is below).
///CODE TO BE FOCUSED ON
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
public class game extends JFrame {
static long z;
game()
{
add(new board());
setBounds(0, 0, 500, 500);
setVisible(true);
setLayout(null);
setLocationRelativeTo(null);
setTitle("\t\t...................::::~~~~'S GAME~~~~:::::...............");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new game();
z = System.currentTimeMillis();
}
}
class board extends JPanel implements ActionListener
{
Timer t = new Timer(5, this);
public ArrayList alien_list;
craft craft_list = new craft();
Label l = new Label();
int total_hits = 0;
public board() {
setFocusable(true);
setLayout(null);
setDoubleBuffered(true);
setBackground(Color.BLACK);
addKeyListener(craft_list);
l.setBounds(0, 0, 150, 30);
l.setBackground(Color.GREEN);
add(l);
t.start();
alien_list = new ArrayList();
alien_list.add(new alien(0, 100));
alien_list.add(new alien(0, 150));
alien_list.add(new alien(0, 200));
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g1 = (Graphics2D) g;
long z = (System.currentTimeMillis() - game.z) / 1000;
if (z >= 60)
{
remove(l);
g.setColor(Color.red);
g1.drawString("time up", 100, 100);
} else
{
g1.drawImage(craft_list.getImage(), craft_list.getX(),
craft_list.getY(), null);
ArrayList a = craft_list.getmissile();
for (int i = 0; i < a.size(); i++) {
missile m = (missile) a.get(i);
g1.drawImage(m.getImage(), m.getX(), m.getY(), null);
}
l.setText("time elapsed:" + " " + +z + " " + "hits:" + " "
+ total_hits);
for (int i = 0; i < alien_list.size(); i++) {
alien m = (alien) alien_list.get(i);
g1.drawImage(m.getImage(), m.getX(), m.getY(), null);
}
}
}
public void actionPerformed(ActionEvent e) {
ArrayList a = craft_list.getmissile();
for (int i = 0; i < a.size(); i++) {
missile m = (missile) a.get(i);
if (m.visible == true)
m.move();
else
a.remove(i);
}
long z = (System.currentTimeMillis() - game.z) / 1000;
if (z % 3 == 0)
alien_list.add(new alien(-10, 100));
for (int j = 0; j < alien_list.size(); j++) {
alien m = (alien) alien_list.get(j);
if (m.visible == true)
m.move();
else
alien_list.remove(j);
}
craft_list.move();
collison();
repaint();
}
public void collison() {
ArrayList a = craft_list.getmissile();
for (int i = 0; i < a.size(); i++) {
missile m = (missile) a.get(i);
Rectangle r1 = m.getBounds();
for (int j = 0; j < alien_list.size(); j++) {
alien l = (alien) alien_list.get(j);
Rectangle r2 = l.getBounds();
if (r1.intersects(r2)) {
total_hits++;
m.setVisible(false);
l.setVisible(false);
}
}
}
}
}
class craft extends KeyAdapter
{
int x = 250;
int y = 400;
ArrayList m = new ArrayList();
Image i;
int dx, dy;
craft() {
ImageIcon i1 = new ImageIcon("1a.jpg");
i = i1.getImage();
}
public Image getImage() {
return i;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void move() {
x += dx;
y += dy;
if (x < 0)
x = 0;
if (x > 450)
x = 450;
if (y > 420)
y = 420;
if (y < 200)
y = 200;
}
public void keyPressed(KeyEvent k)
{
int key = k.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
fire();
}
if (key == KeyEvent.VK_LEFT) {
dx = -1;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 1;
}
if (key == KeyEvent.VK_UP) {
dy = -1;
}
if (key == KeyEvent.VK_DOWN) {
dy = 1;
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = 0;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 0;
}
if (key == KeyEvent.VK_UP) {
dy = 0;
}
if (key == KeyEvent.VK_DOWN) {
dy = 0;
}
}
public void fire() {
m.add(new missile(getX() + 13, getY() - 6));
}
public ArrayList getmissile() {
return m;
}
public Rectangle getBounds() {
return new Rectangle(x, y, i.getWidth(null), i.getHeight(null));
}
}
class missile {
Image i;
int x, y;
public boolean visible;
missile(int x, int y) {
this.x = x;
this.y = y;
visible = true;
ImageIcon i1 = new ImageIcon("1c.jpg");
i = i1.getImage();
}
public Image getImage() {
return i;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void move() {
y--;
if (y < 0)
visible = false;
}
public Rectangle getBounds() {
return new Rectangle(x, y, i.getWidth(null), i.getHeight(null));
}
public void setVisible(boolean t) {
this.visible = t;
}
}
class alien {
Image i;
int x, y;;
public boolean visible;
public alien(int x, int y)
{
this.x = x;
this.y = y;
ImageIcon i1 = new ImageIcon("b.jpg");
i = i1.getImage();
visible = true;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Image getImage() {
return i;
}
public void move() {
x++;
if (x > 500)
visible = false;
}
public Rectangle getBounds() {
return new Rectangle(x, y, i.getWidth(null), i.getHeight(null));
}
public void setVisible(boolean t) {
this.visible = t;
}
}
Ok, your code format is kind of unreadable and invites everybody to oversee otherwise obvious bugs. That is what I have seen so far for your performance issue:
getBounds() creates a new Rectangle instance every time it gets called. You should update the bounds rectangle at the last line of your move() and just return the rectangle instance instead of creating a new one.
Reuse Image or ImageIcon objects. There is no need to load the same jpg file over and over again in a constructor. Make it static or use a image cache.
Instead of o++ in fire() you should use o = m.size(). Mainly because you never call o--, you only remove the rocket from the ArrayList.
And at that point everybody loses track of what o and m means. Name your variables better! o should be amountOfRockets and m should be listOfRockets.
When you use Eclipse, press ctrl + shift + f to format the code which I highly recommend. After that go through your code and name the variables correctly. That means you should give them a descriptive name. And finally: let the name of your classes start with an upper case.
Very likely that this will not yet remove all issues but it will at least help us to understand and read your code easier... which might lead us to a solution...
Update:
You still haven't done 1. and 2. I suggested but you did 3.
Here is what 1. should be as a sample for the Alien class:
private Rectangle bounds
//constructor
Alien() {
// your stuff and the bounds:
bounds = new Rectangle(x, y, i.getWidth(null), i.getHeight(null));
}
public void move() {
bounds.x++;
if (bounds.x > 500)
visible = false;
}
public Rectangle getBounds() {
return bounds;
}
You need to implement that for the Rocket class as well.
What I still don't get is where you remove the old Alien objects. Just setting their visibility is not enough. You should remove them from the list of your Alien objects. Otherwise you will loop through objects that are not there anymore.
I have made a kind of gravity in a 2D Java game and I am attempting to create a jumping algorithm. I have had a look around and cannot seen to find any help for an algorithm which moves up and down in a wave.
Here is the code in Game.java:
package game;
import java.awt.*;
public class Game extends GameLoop{
public void init(){
setSize(864,480);
Thread th = new Thread(this);
th.start();
offscreen = createImage(864,480);
d = offscreen.getGraphics();
addKeyListener(this);
}
public void paint(Graphics g){
d.clearRect(0, 0, 864, 480);
d.drawImage(background, 0, 0, this);
d.drawImage(person, x, y, this);
g.drawImage(offscreen, 0, 0, this);
}
public void update(Graphics g){
paint(g);
}
}
And here is the code in GameLoop.java:
package game;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.*;
public class GameLoop extends Applet implements Runnable, KeyListener{
public int x, y;
public Image offscreen;
public Graphics d;
public boolean up, down, left, right;
public BufferedImage background, w1, w2, w3, w4, w5, w6, w7, w8, person, s1, s2;
public int counter, counter2;
public void run(){
x = 100;
y = 100;
try {
background = ImageIO.read(new File("background.png"));
w1 = ImageIO.read(new File("walk1.png"));
w2 = ImageIO.read(new File("walk2.png"));
w3 = ImageIO.read(new File("walk3.png"));
w4 = ImageIO.read(new File("walk4.png"));
w5 = ImageIO.read(new File("walk5.png"));
w6 = ImageIO.read(new File("walk6.png"));
w7 = ImageIO.read(new File("walk7.png"));
w8 = ImageIO.read(new File("walk8.png"));
s1 = ImageIO.read(new File("stancel.png"));
s2 = ImageIO.read(new File("stancer.png"));
} catch (IOException e1) {
e1.printStackTrace();
}
person = s1;
while(true){
x = 100;
y = 100;
while(true){
if (y <= 304 && up != true){
y+=10;
}
counter++;
counter2++;
if (counter >= 20){
counter = 0;
}
if (counter >= 0 && counter <= 5 && right == true){
person = w1;
}
if (counter > 5 && counter < 10 && right == true){
person = w2;
}
if (counter >= 10 && counter <= 15 && right == true){
person = w3;
}
if (counter > 15 && right == true){
person = w4;
}
if (counter2 >= 20){
counter2 = 0;
}
if (counter2 >= 0 && counter2 <= 5 && left == true){
person = w5;
}
if (counter2 > 5 && counter2 < 10 && left == true){
person = w6;
}
if (counter2 >= 10 && counter2 <= 15 && left == true){
person = w7;
}
if (counter2 > 15 && left == true){
person = w8;
}
if (left == true){
x-=4;
}
if (right == true){
x+=4;
}
if (up == true){
y-=4;
}
if (down == true){
y+=4;
}
if ( x <= -10 ){
x = -10;
}
if ( y <= 0 ){
y = 0;
}
if ( x >= 824 ){
x = 824;
}
if ( y >= 304 ){
y = 304;
}
repaint();
try{
Thread.sleep(20);
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
//#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == 37){
left = true;
}
if(e.getKeyCode() == 38){
up = true;
}
if(e.getKeyCode() == 39){
right = true;
}
if(e.getKeyCode() == 40){
down = true;
}
}
//#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == 37){
left = false;
person = s2;
}
if(e.getKeyCode() == 38){
up = false;
}
if(e.getKeyCode() == 39){
right = false;
person = s1;
}
if(e.getKeyCode() == 40){
down = false;
}
}
//#Override
public void keyTyped(KeyEvent e) {
}
}
I think I need a counter , counter3 as a double, but I am not sure of an algorithm that will go up to a certain point on the y axis, then move down. Any help is appreciated.
One of the simplest wave functions is our old friend sine:
So for a jump motion, you would probably like the first half of a sine period. You could use java.util.Math, passing a sequence of numbers from 0 to 180 (how many depends on the number of frames you want the jump to last). e.g.:
Math.sin(0.0); // = 0.0
Math.sin(30.0); // = 0.5
Math.sin(60.0); // = 0.9
Math.sin(90.0); // = 1.0
Math.sin(120.0); // = 0.9
Math.sin(150.0); // = 0.5
Math.sin(180.0); // = 0.0
I'm not entirely sure by what you mean by "moves up and down in a wave".
But anyway, in real world physics, the altitude of an object in free-fall (ignoring air resistance) follows a parabola; i.e. it obeys a formula like:
altitude = maxAltitude - (acceleration * (t - timeOfMaxAltitude))^2
(There are other ways of formulating the laws of motion, but this approach is probably what you need for a simple game.)
A 1/2 sine wave looks rather like a truncated parabola, and could be used instead in a game. However, you need to realize that it is not an accurate simulation of real-world physics, especially for high jumps.
You can use a variable to represent the vertical velocity. When you jump, set the vertical velocity to a negative value. On each frame, add the vertical velocity to the vertical position, and add a constant to the velocity to simulate gravity. When there is something underneath, set the velocity back to 0. Experiment with the constant values to get an appropriate jump height.