pengo4k

tell me what do u think about this game:

http://howlerbr.freecoolsite.com/files/pengo4k/pengo.jnlp

It is a 4k version of the ld classic Pengo

nice!
I’d replace the breakIce g.fillOval(x, y, 1, 1);
for more speed. The game slows linearly down by the amount of broken ice for me

Cool!

Pengo is a classic and this is a very worthy 4K conversion. I had some problems though. At level 4 I could not complete the level. All badies are gone and all (visible ?) coins are gone, but I can’t get to next level. Also agree with Hansdampf. After two broken iceblocks, the game runs at about 1/2 speed from normal! Game should probably also be time based. So player moves same dist / sec independent of CPU speed and load. I guess that is not the case, so on a 3GHz machine this might simply be too fast to play. Badies mouth is upside-down when moving left :smiley: Not sure if that is intentional.

tks for the feedback, I will try to figure out what is happing. But how can I make the player moves same dist / sec independent of CPU speed and load ?

Something like this:

//init
      float playerX;
      long lastLoopTime = System.currentTimeMillis();

      //Main game loop
      while (true) {
            delta = System.currentTimeMillis() - lastLoopTime;
            lastLoopTime = System.currentTimeMillis();

            //Use delta for all your movement!

            //Move
            if(left){
                  playerX -= delta * 0.01f;
            }
            if(right){
                  playerX += delta * 0.01f;
            }

            //All your other gamecode
      }

Short description, but I think you get the idea

I have tried the following code:


import java.awt.Color;
import java.awt.Toolkit;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.io.InputStream;

import javax.swing.JFrame;

public class Loop1 extends JFrame {

      private boolean[] controls = new boolean[5];
      int x=100;
      int y=100;
      double dx=0.1;
      double dy=0.1;

      public Loop1() {
   
            setSize(300,300);
            setResizable(false);
            show();
 
             enableEvents(56);
   
            createBufferStrategy(2);
            BufferStrategy strategy = getBufferStrategy();
 
            int FPS=60;
            int MILI_FRAME_LENGTH = 1000/FPS;
            long startTime = System.currentTimeMillis();
            int frameCount = 0;

            long lastLoopTime = System.currentTimeMillis(); 
            long lastFpsTime=0;
            long fps=0;

            while (true) {

                  long delta = System.currentTimeMillis() - lastLoopTime;
                  lastLoopTime = System.currentTimeMillis();
                   lastFpsTime += delta;
                  fps++;
 
                   if (lastFpsTime >= 1000) {
                        this.setTitle(" (FPS: " + fps + ")");
                        lastFpsTime = 0;
                        fps = 0;
                  } 

                     logic(delta);
                        draw((Graphics2D) strategy.getDrawGraphics());
                        strategy.show();

                  frameCount++;
                  while((System.currentTimeMillis()-startTime)/MILI_FRAME_LENGTH <frameCount) {
                        Thread.yield();
                  } 

                  //Toolkit.getDefaultToolkit().sync(); 

            }
      } 

      private void logic(double delta) {
            if(controls[0]) {
                  x-=dx*delta;
            } else if(controls[1]) {
                  x+=dx*delta;
            } else if(controls[2]) {
                  y-=dy*delta;
            } else if(controls[3]) {
                  y+=dy*delta;
            }

            if(x>300) {
                  x=0;
            }
            if(x<0) {
                  x=300;
            }
            if(y<0) {
                  y=300;
            }
            if(y>300) {
                  y=0;
            }

      }

      private void draw(Graphics2D g) {
            g.setColor(Color.white);
            g.fillRect(0,0,300,300);

            g.setColor(Color.red);
            g.fillOval(x,y,5,5);

      }


      protected void processKeyEvent(KeyEvent e) {
            int[] keys = new int[] {KeyEvent.VK_LEFT,KeyEvent.VK_RIGHT,KeyEvent.VK_UP,KeyEvent.VK_DOWN,KeyEvent.VK_SPACE};
            for (int i=0;i<keys.length;i++) {
                  if (e.getKeyCode() == keys[i]) {
                        controls[i] = e.getID() == KeyEvent.KEY_PRESSED;
                  }
            }
            if (e.getKeyCode() == 27) {
                  System.exit(0);
            }
        } 

      public static void main(String argv[]) {
            new Loop1();
      }

}

But it seems to move the dot point faster when I move up and left and slower when I move down and right… Ihave another post in the forum with the same question.

This code follows what you said to do…what is wrong?
The only difference is that I am using ints for x and y instead of floats

I think that the problem was exactlly that. Now I am using double for x,y and delta, instead of int for x,y and long for delta. Now it seems to move at the same speed in all directions…but I did not understand why it did not work with ints…any ideas?

(int)(5+0.3) //this = 5
(int)(5-0.3) //this = 4

Typecasting float to int will not round off, but just take away decimals.

now I am using

double x;
double y;
double dx;
double dy;
long delta;

// updating according to delta variation
x-=dxdelta;
y-=dx
delta;

// drawing the player
g.fillOval((int)x,(int)y,5,5);

It seems to be working but I don’t know if it the best practice.

I always heard that is preferred to use ints instead of double or floats to get more performance

[quote]I always heard that is preferred to use ints instead of double or floats to get more performance
[/quote]
Premature optimization is the root of all evil. Besides, minor optimizations at an instruction level tend to make very little difference on modern hardware. You’ll do much better investing your time in finding a solution that’s algorithmically faster.

jojoh and jbanes, I have just one more question:

If I do not use delta for update my movement, how can I maintain the same speed with different CPUs?

Say if I wanna move my player 3 pixels every time a press a directional key?

x+=3 if going right
x-=3 if going left
y+=3 if goinf down
y-=3 if goinf up.

How should I do that?

Then you want to have a set frame rate. Also, you shouldn’t actually make them move whenever a key is pressed as the KeyEvent Thread is not in synch with your game… so take a look at my tutorial to see a good way to manage frame based animation as you’re desiring:

http://www.gamelizard.com/JavaGameProgrammingPresentation.htm

I am taking a look at your game loop. I did not understand this:

//Doesn’t account for drag
tick = at.getClockTicks();

//Does account for drag
//tick += ticksPerFrame;

What exactly means “account” for drag? And when I should use one or another?

Also, was not clear to me why did you mix GageTimer with System.currentTimeMillis() ?

umm…is webstart foobared or somethin?! Or are you lying to us telling us its 4K? huh? :stuck_out_tongue:

http://www.myjavaserver.com/~digiwired/4KOr7.jpg

Oh yer, good game, i used to be an addict on it on www.javaonthebrain.com.

Still a cool game!

DP

the webstart jar version is bigger. The final version for 4k competition I have used proguard to shrink the size, and it is lower than 4k…

here is the url:

http://howlerbr.freecoolsite.com/files/pengo4k/pengo4k.jar

Download it and execute…

java -jar pengo4k.jar P

Malohkan, I have implemented your game loop example. It works, but please answer my previous questions for a better understanding. Tks in advance! :smiley:

As for mixing timing techniques, there’s no need for that other than it’s simple to show how to calculate FPS. You can use GAGE to get the time just as easily for that purpose.

As for your timing question, drag means time lost due to the cpu working too hard on something. The idea is that if you’re unable to evaluate all of your game stuff in a single frame’s time, the next frame will try to be faster to make up for it. This can be good for when you really care about true time elapsed.

However for many of my purposes, any time I have drag, it’s long lag, generally a spike from something unforseeable. So I really don’t want the next 10 frames to be really quick because I’m in an action game where you fight AI, so that gives the CPU a big advantage. Not only does it suck to have the game freeze, but it sucks worse to see the AI get 10 shots on you when you barely have time to react. So really it’s a matter of trying both out to see which is right for your purpose. Ideally your game won’t require so much time and they’ll both work the same :slight_smile:

thank you Malohkan, your explanation really cleared out my questions! ;D

It ran great on my machine… Good Job.