views:

132

answers:

4
+1  Q: 

game speed problem

HI..I made a little game.But this game works on every computer with different speed.I think it is about resolution.I used every thing in paintcomponent.and If I change screen size the game goes slower or faster.And if i run this game on another computer wich has different resolution it also works different. This is my game
http://rapidshare.com/files/364597095/ShooterGame.2.6.0.jar

and here code

public class Shooter extends JFrame implements KeyListener, Runnable {

JFrame frame = new JFrame();
String player;
Font startFont, startSubFont, timerFont,healthFont;
Image img;
Image backGround;
Graphics dbi;
URL url1 = this.getClass().getResource("Images/p2.gif");
URL url2 = this.getClass().getResource("Images/p3.gif");
URL url3 = this.getClass().getResource("Images/p1.gif");
URL url4 = this.getClass().getResource("Images/p4.gif");
URL urlMap = this.getClass().getResource("Images/zemin.jpg");
Player p1 = new Player(5, 150, 10, 40, Color.GREEN, url3);
Computer p2 = new Computer(750, 150, 10, 40, Color.BLUE, url1);
Computer p3 = new Computer(0, 0, 10, 40, Color.BLUE, url2);
Computer p4 = new Computer(0, 0, 10, 40, Color.BLUE, url4);
ArrayList<Bullets> b = new ArrayList<Bullets>();
ArrayList<CBullets> cb = new ArrayList<CBullets>();
Thread sheap;
boolean a, d, w, s;
boolean toUp, toDown;
boolean GameOver;

boolean Level2;
boolean newGame, resart, pause;
int S, E;
int random;
int cbSpeed = 0;
long timeStart, timeEnd;
int timeElapsed;
long GameStart, GameEnd;
int GameScore;
int Timer = 0;
int timerStart, timerEnd;

public Shooter() {


    sheap = new Thread(this);
    sheap.start();
    startFont = new Font("Tiresias PCFont Z", Font.BOLD + Font.ITALIC, 32);
    startSubFont = new Font("Tiresias PCFont Z", Font.BOLD + Font.ITALIC, 25);
    timerFont = new Font("Tiresias PCFont Z", Font.BOLD + Font.ITALIC, 16);
     healthFont = new Font("Tiresias PCFont Z", Font.BOLD + Font.ITALIC, 16);
    setTitle("Shooter 2.5.1");
    setBounds(350, 250, 800, 600);

    // setResizable(false);
    setBackground(Color.black);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    addKeyListener(this);
    a = d = w = s = false;
    toUp = toDown = true;
    GameOver = true;
    newGame = true;
    Level2 = false;
    S = E = 0;

    setVisible(true);

}

public void paint(Graphics g) {

    img = createImage(getWidth(), getHeight());
    dbi = img.getGraphics();
    paintComponent(dbi);
    g.drawImage(img, 0, 0, this);

}

public void paintComponent(Graphics g) {
   repaint();
    timeStart = System.currentTimeMillis();
    backGround = Toolkit.getDefaultToolkit().getImage(urlMap);
    g.drawImage(backGround, 0, 0, null);
    g.setColor(Color.red);
   g.setFont(healthFont);
    g.drawString("" + player + " Health : " + p1.health, 30, 50);
    g.setColor(Color.red);
    g.drawString("Computer Health : " + (p2.health + p3.health + p4.health), 600, 50);
    g.setColor(Color.BLUE);
    g.setFont(timerFont);
    g.drawString("Time  : " + Timer, 330, 50);
    if (newGame) {

        g.setColor(Color.LIGHT_GRAY);
        g.setFont(startFont);
        g.drawString("Well Come To Shoot Game", 200, 190);
        g.drawString("Press ENTER To Start", 250, 220);
        g.setColor(Color.LIGHT_GRAY);
        g.setFont(startSubFont);
        g.drawString("Use W,A,S,D and Space For Fire", 200, 250);
        g.drawString("GOOD LUCK", 250, 280);

       newGame();

    }
    if (!GameOver) {

        for (Bullets b1 : b) {

            b1.draw(g);
        }
        for (CBullets b2 : cb) {

            b2.draw(g);

        }
        update(); // Here MOvements for Player and For Fires
    }
    if (p1.health <= 0) {
        g.setColor(p2.col);
        g.setFont(startFont);
        g.drawString("Computer Wins ", 200, 190);
        g.drawString("Press Key R  to Restart ", 200, 220);
        GameOver = true;

    } else if (p2.health <= 0 && p3.health <= 0 && p4.health <= 0) {

        g.setColor(p1.col);
        g.setFont(startFont);
        g.drawString(""+player+" Wins ", 200, 190);
        g.drawString("Press Key R  to Resart ", 200, 220);
        GameOver = true;


        g.setColor(Color.MAGENTA);
        g.drawString(""+player+"`s  Score is " + Timer, 200, 120);


    }

    if (Level2) {
        if (p3.health >= 0) {
            p3.draw(g);

            for (CBullets b3 : cb) {
                b3.draw(g);
            }
        } else {
            p3.x = 1000;
        }

        if (p4.health >= 0) {
            p4.draw(g);

            for (CBullets b4 : cb) {
                b4.draw(g);
            }
        } else {
            p4.x = 1000;
        }
    }
    if (p1.health >= 0) {
        p1.draw(g);

    }
    if (p2.health >= 0) {
        p2.draw(g);
    } else {
        p2.x = 1000;
    }

}

public void update() {


    if (w && p1.y > 54) {
        p1.moveUp();
    }

    if (s && p1.y < 547) {
        p1.moveDown();
    }
    if (a && p1.x > 0) {
        p1.moveLeft();
    }

    if (d && p1.x < 200) {
        p1.moveRight();
    }
    random = 1 * (int) (Math.random() * 100);

    if (random > 96) {
        if (p2.health >= 0) {
            CBullets bo = p2.getCBull();

            bo.xVel =-1-cbSpeed;

            cb.add(bo);
        }
        if (Level2) {
            if (p3.health >= 0) {
                CBullets bo1 = p3.getCBull();
                bo1.xVel = -2-cbSpeed;
                cb.add(bo1);
            }
            if (p4.health >= 0) {
                CBullets bo2 = p4.getCBull();
                bo2.xVel = -4-cbSpeed;
                cb.add(bo2);
            }
        }

    }

    if (S == 1) {

        if (p1.health >= 0) {
            Bullets bu = p1.getBull();
            bu.xVel = 5;
            b.add(bu);
            S += 1;
        }
    }

    //Here Also Problem .. When COmputer have More fire then it gaves Array Exeption . Or Player have More Fire
for (int i = cb.size() -1; i >= 0 ; i--) {
        boolean bremoved = false;
    for (int j = b.size() -1 ; j >=0 ; j--) {
        if (b.get(j).rect.intersects(cb.get(i).rect) ||
            cb.get(i).rect.intersects(b.get(j).rect)) {
              bremoved = true;
            b.remove(j);
        }
    }
    if(bremoved)
        cb.remove(i);
}






    for (int i = 0; i < b.size(); i++) {
        b.get(i).move();

        if (b.get(i).rect.intersects(p2.rect)) {

            if (p2.health >= 0) {
                p2.health--;

                b.remove(i);
           //     System.out.println("Hited P2");
                i--;

                continue;
            }
        }

        if (b.get(i).rect.intersects(p3.rect)) {
            if (p3.health >= 0) {
                p3.health--;

                b.remove(i);
             //   System.out.println("Hited P3");
                i--;

                continue;
            }
        }
        if (b.get(i).rect.intersects(p4.rect)) {
            if (p4.health >= 0) {
                p4.health--;

                b.remove(i);
             //   System.out.println("Hited P4");
                i--;

                continue;
            }
        }
        if (b.get(i).rect.x > 790) {
            b.remove(i);

        }
    }

    for (int j = 0; j < cb.size(); j++) {
        cb.get(j).move();

        if (cb.get(j).rect.intersects(p1.rect) && cb.get(j).xVel < 0) {

            p1.health--;
            cb.remove(j);
            j--;
            continue;
        }
    }

    timeEnd = System.currentTimeMillis();
    timeElapsed = (int) (timeEnd - timeStart);
}

public void level2() {

    if (p2.health <= 10) {

        Level2 = true;
        cbSpeed = 4;
        p3.x = 750;
        p4.x = 750;

        p2.speed = 10;
        p3.speed = 20;
        p4.speed = 30;
    }
}

public void keyTyped(KeyEvent e) {
}

public void keyPressed(KeyEvent e) {
    switch (e.getKeyCode()) {
        case KeyEvent.VK_ENTER:
            newGame = false;

            break;
        case KeyEvent.VK_P:
            pause = true;

            break;
        case KeyEvent.VK_R:
            resart = true;

            break;
        case KeyEvent.VK_A:
            a = true;

            break;

        case KeyEvent.VK_D:
            d = true;
            break;
        case KeyEvent.VK_W:
            w = true;
            break;
        case KeyEvent.VK_S:
            s = true;
            break;

        case KeyEvent.VK_SPACE:
            S += 1;

            break;
    }
}

public void keyReleased(KeyEvent e) {
    switch (e.getKeyCode()) {

        case KeyEvent.VK_A:
            a = false;
            break;
        case KeyEvent.VK_D:

            d = false;
            break;
        case KeyEvent.VK_W:
            w = false;
            break;
        case KeyEvent.VK_S:
            s = false;
            break;

        case KeyEvent.VK_SPACE:
            S = 0;

            break;

    }
}

public void newGame() {

    p1.health = 20;
    p2.health = 20;
    p3.health = 20;
    p4.health = 20;
    p3.x = 0;
    p4.x = 0;
    p2.x = 750;

    Level2 = false;
    cbSpeed = 0;
    p2.speed = 9;
    b.removeAll(b);
    cb.removeAll(cb);

    timerStart = (int) System.currentTimeMillis();

    GameOver = false;

}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        public void run() {
            KeyListener k = new Shooter();
        }
    });

}

@Override
public void run() {
    player = JOptionPane.showInputDialog(frame, "Enter Player Name", "New Player", JOptionPane.DEFAULT_OPTION);

    while (true) {

        timerEnd = (int) System.currentTimeMillis();

        if (resart) {
            newGame();
            resart = false;
        }
        if (pause) {
            Thread.currentThread().notify();
        }
        try {

            if (!GameOver) {
Timer = timerEnd - timerStart;
                level2();
                if (p1.y < p2.y && p2.y>60) {
                    p2.moveUp();
                }
                if (p1.y < p3.y && p3.y>43) {
                    p3.moveUp();
                }
                if (p1.y < p4.y && p4.y>43) {
                    p4.moveUp();

                }
                if (p1.y > p2.y && p2.y<535) {
                    p2.moveDown();
                }
                if (p1.y > p3.y && p3.y<535) {
                    p3.moveDown();
                }
                if (p1.y > p4.y && p4.y<530) {
                    p4.moveDown();
                }

            }
            if (timeElapsed < 125) {
                Thread.currentThread().sleep(125);
            }
        } catch (InterruptedException ex) {
            System.out.print("FInished");

        }

    }

}

}

+4  A: 

It's hard to tell from your splurge, but I'm going to go right ahead and answer anyway: The problem seems to be that you don't drop frames; only stall them. basically, you need to separate your game logic from your drawing logic, and draw however many frames you can. The two should probably be on different threads, but then again, threads are evil.

Williham Totland
Threads are good as long as you use the appropriate wrappers or libraries. Like SwingWorker, Future's etc.
extraneon
+1 for separating concerns though, you'd imagine everyone ought to know that by now:)
extraneon
@ Williham You mean I must create another paint methon and use it in thread?
Meko
@Meko: I mean that you must take whatever power you need for each game tick and try your hardest to get each one calculated in time. A frame of animation is just a snapshot of the game state at any given moment. Ensure the game state is moving along at the right pace, and take (and draw) however many snapshots you can. That way, if you find you can't do 30 FPS, you can drop down to 20; and the game state will still be moving at (more or less) the same pace.
Williham Totland
+3  A: 

The topic you are looking for is "Time based movement". I did not read your source code, but the behavior you described looks like frame based movement is the problem.

Here is a short tutorial which covers Time based movement: http://jerome.jouvie.free.fr/OpenGl/Tutorials/Tutorial10.php

This post also covers the problem in greater detail and focuses at physics but also apply to rather simple games: http://gafferongames.com/game-physics/fix-your-timestep/

Edit: As the other answer states, separating rendering and game logic greatly helps.

Malax
A: 

You need to keep track of the number of millisecs since the last "tick" (screen redraw probably) and only update your world state (positions for instance) when a certain amount of time has passed. Otherwise your game will run at the speed of screen redraws which is not consistent.

Lets say you want to run at 25 fps, that means you should update the game state 25 times per second at most, ie every 40th millisecond.

Martin Wickman
A: 

HI again..I made some modıfıcation to my game like drawing and moving objects in thread..Now it workы on every сomputer same speed.Also if I change size.But problem is I used J3DTimer.getValue() .For this library I donwnloaded Java3d. Problem is If on machine there is no this library or installation my game doesnot working .How can I solw this problem? I should say every one to setup Java#d? :)) ALso I used standart System.currentTimeMillis(); but now my game works very slow...Any idea?

Meko
Either edit this post into your original question, or start a new thread. The "Answers" part of each thread is meant only for answers. Answers are not arranged by when they were written, so discussions like this don't really work.
Wallacoloo
@Wallacoloo Thanks for advice.
Meko