Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (497)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Stuttering and rending issues in java4k game  (Read 1406 times)
0 Members and 1 Guest are viewing this topic.
Offline Jens_S
« Posted 2013-01-12 13:28:39 »

Hi guys!

I've made a little avoid'em'up-game for this years Java4k. It runs smooth on some computers, but when I test it on one some "older" computers the animation is a bit jerky and I run into some irritating stuttering  Sad.

I have these problems on an older Linux laptop (in Firefox), and an older Windows 7 box (in Internet Explorer). However, when I run Chrome on these computers the game runs fine  Huh.

I've made some Java2D games before, but I have not experience rendering issues then. For example, my entry for last years Java4K runs just fine.

I've done everything I can think of (even desperate things): testing with different timing approaches, busy timing looping, non-busy timing looping, reducing painting operations, removing object allocations, reducing floating number operations, removing code, and so on... but nothing seems to solve this. Obviously I'm optimizing the wrong things, and I have a hard time to find the real issue.

This is starting to drive me crazy. What am I doing wrong? Do you have any suggestions?

I'm attaching the source code for the project. It's not very many lines of code, but since it's a Java4K-project the readability may not be the best. Just ask me if you need any specific details or info.

If someone wants to help me I would be very happy and grateful.
Help me JavaGaming, you are my only hope!

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
208  
209  
210  
211  
212  
213  
214  
215  
216  
217  
218  
219  
220  
221  
222  
223  
224  
225  
226  
227  
228  
229  
230  
231  
232  
233  
234  
235  
236  
237  
238  
239  
240  
241  
242  
243  
244  
245  
246  
247  
248  
249  
250  
251  
252  
253  
254  
255  
256  
257  
258  
259  
260  
261  
262  
263  
264  
265  
266  
267  
268  
269  
270  
271  
272  
273  
274  
275  
276  
277  
278  
279  
280  
281  
282  
283  
284  
285  
286  
287  
288  
289  
290  
291  
292  
293  
294  
295  
296  
297  
298  
299  
300  
301  
302  
303  
304  
305  
306  
307  
308  
309  
310  
311  
312  
313  
314  
315  
316  
317  
318  
319  
320  
321  
322  
323  
324  
325  
326  
327  
328  
329  
330  
331  
332  
333  
334  
335  
336  
337  
338  
339  
340  
341  
342  
343  
344  
345  
346  
347  
348  
349  
350  
351  
352  
353  
354  
355  
356  
357  
358  
359  
360  
361  
362  
363  
364  
365  
366  
367  
368  
369  
370  
371  
372  
373  
374  
375  
376  
377  
378  
379  
380  
381  
382  
383  
384  
385  
386  
387  
388  
389  
390  
391  
392  
393  
394  
395  
396  
397  
398  
399  
400  
401  
402  
403  
404  
405  
406  
407  
408  
409  
410  
411  
412  
413  
414  
415  
416  
417  
418  
419  
420  
421  
422  
423  
424  
425  
426  
427  
428  
429  
430  
431  
432  
433  
434  
435  
436  
437  
438  
439  
440  
441  
442  
443  
444  
445  
446  
447  
448  
449  
450  
451  
452  
453  
454  
455  
456  
457  
458  
459  
460  
461  
462  
463  
464  
465  
466  
467  
468  
469  
470  
471  
472  
473  
474  
475  
476  
477  
478  
479  
480  
481  
482  
483  
484  
485  
486  
487  
488  
489  
490  
491  
492  
493  
494  
495  
496  
497  
498  
499  
500  
501  
502  
503  
504  
505  
506  
507  
508  
509  
510  
511  
512  
513  
514  
515  
516  
517  
518  
519  
520  
521  
522  
523  
524  
525  
526  
527  
528  
529  
530  
531  
532  
533  
534  
535  
536  
537  
538  
539  
540  
541  
542  
543  
544  
545  
546  
547  
548  
549  
550  
551  
552  
553  
554  
555  
556  
557  
558  
559  
560  
561  
562  
563  
564  
565  
566  
567  
568  
569  
570  
571  
572  
573  
574  
575  
576  
577  
578  
579  
580  
581  
582  
583  
584  
585  
586  
587  
588  
589  
590  
591  
592  
593  
594  
595  
596  
597  
598  
599  
600  
601  
602  
603  
604  
605  
606  
607  
608  
609  
610  
611  
612  
613  
614  
615  
616  
617  
618  
619  
620  
621  
622  
623  
624  
625  
626  
627  
628  
629  
630  
631  
632  
633  
634  
635  
636  
637  
638  
639  
640  
641  
642  
643  
644  
645  
646  
647  
648  
649  
650  
651  
652  
653  
654  
655  
656  
657  
658  
659  
660  
661  
662  
663  
664  
665  
666  
667  
668  
669  
670  
671  
672  
673  
674  
675  
676  
677  
678  
679  
680  
681  
682  
683  
684  
685  
686  
687  
688  
689  
690  
691  
692  
693  
694  
695  
696  
697  
698  
699  
700  
701  
702  
703  
704  
705  
706  
707  
708  
709  
710  
711  
712  
713  
714  
715  
716  
717  
718  
719  
720  
721  
722  
723  
724  
725  
726  
727  
728  
729  
730  
731  
732  
733  
734  
735  
736  
737  
738  
739  
740  
741  
742  
743  
744  
745  
746  
747  
748  
749  
750  
751  
752  
753  
754  
755  
756  
757  
758  
759  
760  
761  
762  
763  
764  
765  
766  
767  
768  
769  
770  
771  
772  
773  
774  
775  
776  
777  
778  
779  
780  
781  
782  
783  
784  
785  
786  
787  
788  
789  
790  
791  
792  
793  
794  
795  
796  
797  
798  
799  
800  
801  
802  
803  
804  
805  
806  
807  
808  
809  
810  
811  
812  
813  
814  
815  
816  
817  
818  
819  
820  
821  
822  
823  
824  
825  
826  
827  
828  
829  
830  
831  
832  
833  
834  
835  
836  
837  
838  
839  
840  
841  
842  
843  
844  
845  
846  
847  
848  
849  
850  
851  
852  
853  
854  
855  
856  
857  
858  
859  
860  
861  
862  
863  
864  
865  
866  
867  
868  
869  
870  
871  
872  
873  
874  
875  
876  
877  
878  
879  
880  
881  
882  
883  
884  
885  
886  
887  
888  
/*
 * Legend of the package delivering hero
 * Copyright (C) 2012 Jens Stääf
 *
 * Legend of the package delivering hero is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */


import java.applet.Applet;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.Random;

public class G extends Applet implements Runnable {
   // SIZE
  static final int WINDOW_WIDTH = 320;
   static final int WINDOW_HEIGHT = 480;
   static final int MAP_WIDTH = 20;
   static final int MAP_HEIGHT = 30;

   // DIRECTION
  static final int UP = 0;
   static final int DOWN = 1;
   static final int LEFT = 2;
   static final int RIGHT = 3;

   // BOOLEAN
  static final int NO = 0;
   static final int YES = 1;

   static final int PLAYER_SPEED = 220;
   static final int STAR_SPEED = 1;
   static final int SUN_SPEED = 1;
   static final int MAX_NUMBER_OF_ENEMIES = 50;

   // ENEMY TYPES
  static final int POWERUP_BOMB = -3;
   static final int POWERUP_SCORE = -2;
   static final int POWERUP_HEALTH = -1;
   static final int ENEMY_STRAIGHT = 0;
   static final int ENEMY_BOUNCING = 1;
   static final int ENEMY_HOMING = 2;
   static final int ENEMY_TERMINATOR = 3;
   static final int ENEMY_NARROWER = 4;
   static final int ENEMY_CONFUSER = 5;
   static final int ENEMY_BLACKHOLE = 6;

   // ENEMY SPEED
  static final int ENEMY_SPEED_Y = 3;
   static final int ENEMY_SPEED_X = 2;

   // BUTTONS
  static int KEY_LEFT;
   static int KEY_RIGHT;
   static int KEY_UP;
   static int KEY_DOWN;
   static int KEY_SPACE;

   // STATES
  static final int STATE_TITLE = 0;
   static final int STATE_START = 1;
   static final int STATE_BREIFING = 2;
   static final int STATE_LEVELCOMPLETED = 3;
   static final int STATE_RUNNING = 4;
   static final int STATE_GAMEOVER = 5;

   // SCORE LIMITS, USED FOR CALCULATING ADAPTIVE DIFFICULTY
  static final int SCORE_LIMIT_1 = 300;
   static final int SCORE_LIMIT_2 = 500;

   // PLANETS
  static final String[] planets = { "Mercury", "Venus", "Earth", "Mars",
         "Jupiter", "Saturn", "Uranus" };

   // PARTICLES
  static final int MAX_NUMBER_OF_PARTICLES = 50;
   static final int NUMBER_OF_PARTICLES_IN_EXPLOSION = 20;
   static final int NUMBER_OF_PARTICLES_IN_SMALL_EXPLOSION = 5;

   public void start() {
      this.enableEvents(AWTEvent.KEY_EVENT_MASK);
      new Thread(this).start();
   }

   public void run() {
      setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
      BufferedImage screen = new BufferedImage(WINDOW_WIDTH, WINDOW_HEIGHT,
            BufferedImage.TYPE_INT_RGB);
      Graphics g = screen.getGraphics();
      Graphics appletGraphics = getGraphics();
      Random random = new Random();

      // Variable for looping
     int i = 0;
      int a = 0;
      int b = 0;

      // Tile sizes
     int TILE_SIZE = 16;
      int TILE_SIZE_QUARTER = 4;

      // Set up player
     int playerX = 160;
      int playerY = 440;
      int playerVelocityX = 0;
      int playerVelocityY = 0;
      int[] playerXPoints = new int[3];
      int[] playerYPoints = new int[3];
      int score = -10;
      int health = 5;

      // Level
     int scoreLimit = 30;
      int level = 0;

      // Timings
     int timeBeforePlanet = 0;
      int currentPlanetIndex = 0;
      int flickerCounter = 0;
      int powerupTimer = 1200;

      // Ship status effects
     int confused = 0;
      int narrowTimer = 0;
      int isHit = 0;
      int isPower = 0;

      // Enemy animation
     int animationCounter = 0;
      int animationFactor = 0;
      int animationEnlarge = NO;

      int blackHoleinPlace = NO;

      // Set up enemies
     int[] enemyX = new int[MAX_NUMBER_OF_ENEMIES];
      int[] enemyY = new int[MAX_NUMBER_OF_ENEMIES];
      int[] enemyDirection = new int[MAX_NUMBER_OF_ENEMIES];
      int[] enemyType = new int[MAX_NUMBER_OF_ENEMIES];
      int numberOfEnemies = 10;
      int terminatorTimer = 0;
      enemyY[0] = 800;

      // Set up particles
     int[] particleX = new int[MAX_NUMBER_OF_PARTICLES];
      int[] particleY = new int[MAX_NUMBER_OF_PARTICLES];
      int[] particleVelocityX = new int[MAX_NUMBER_OF_PARTICLES];
      int[] particleVelocityY = new int[MAX_NUMBER_OF_PARTICLES];
      int[] particleLife = new int[MAX_NUMBER_OF_PARTICLES];

      int starsX = -100;
      int starsY = 0;
      int sunX = 100;
      int sunY = -200;

      // Game state
     int state = STATE_TITLE;

      // Create star image
     BufferedImage starImage = new BufferedImage(WINDOW_WIDTH + 200,
            WINDOW_HEIGHT, BufferedImage.TYPE_INT_RGB);
      Graphics starGfx = starImage.getGraphics();
      for (i = 0; i < 200; i++) {
         a = random.nextInt(200);
         starGfx.setColor(new Color(250 - a, 250 - a, 250 - a));
         starGfx.fillOval(random.nextInt(WINDOW_WIDTH + 200),
               random.nextInt(WINDOW_HEIGHT), 2, 2);
      }

      BufferedImage sunImage = new BufferedImage(WINDOW_WIDTH, WINDOW_HEIGHT,
            BufferedImage.TYPE_INT_ARGB);
      Graphics sunGfx = sunImage.getGraphics();
      i = random.nextInt(3);
      for (a = 0; a < 150; a++) {
         sunGfx.setColor(new Color(a, 0, a / 2));

         for (b = 0; b < a; b += 1) {
            sunGfx.fillOval(
                  random.nextInt(200 - a) - random.nextInt(200 - a) + 100,
                  random.nextInt(200 - a) - random.nextInt(200 - a) + 150,
                  3, 3);
         }
      }

      // Game loop.
     long nextFrameStartTime = System.nanoTime();
      while (true) {
         // Start the game
        if (state == STATE_START) {
            // Set up the score limit
           scoreLimit = 20;

            // Reset the level
           score = -10;
            level = 0;

            // Set up enemies
           numberOfEnemies = 1;
            terminatorTimer = 0;

            // Reset planet times
           timeBeforePlanet = 0;

            // Remove the black hole
           blackHoleinPlace = NO;

            // Now run the game!
           state = STATE_BREIFING;
         }

         // Set up enemies
        if (state == STATE_RUNNING) {
            for (i = 0; i < numberOfEnemies; i += 1) {
               if (enemyY[i] > WINDOW_HEIGHT) {
                  enemyY[i] = -random.nextInt(WINDOW_HEIGHT);
                  enemyX[i] = random.nextInt(WINDOW_WIDTH);

                  if (score > SCORE_LIMIT_2 && level > 0) {
                     enemyType[i] = random.nextInt(10) - 3;
                  } else if (score > SCORE_LIMIT_1) {
                     enemyType[i] = random.nextInt(7) - 3;
                  } else {
                     enemyType[i] = random.nextInt(6) - 3;
                  }

                  if (enemyType[i] <= POWERUP_HEALTH) {
                     if (powerupTimer == 0) {
                        powerupTimer = 1200;
                     } else {
                        enemyType[i] = ENEMY_STRAIGHT;
                     }
                  }

                  if (enemyType[i] == ENEMY_BLACKHOLE) {
                     enemyX[i] = 160;
                  }

                  // Make sure there's only one terminator at once.
                 // Start the terminator timer.
                 if (enemyType[i] >= ENEMY_TERMINATOR) {
                     if (terminatorTimer == 0) {
                        terminatorTimer = 3000;
                     } else {
                        enemyType[i] = ENEMY_STRAIGHT;
                     }
                  }

                  score += 10;

                  // Create new enemies
                 if (score >= scoreLimit) {
                     if (numberOfEnemies < MAX_NUMBER_OF_ENEMIES - 1) {
                        numberOfEnemies += 1;

                        scoreLimit *= 3;
                        enemyY[numberOfEnemies - 1] = 800;
                     }
                  }
               }

               // Check collision with player
              if (playerX <= (enemyX[i] + TILE_SIZE)
                     && enemyX[i] <= (playerX + TILE_SIZE)
                     && playerY <= (enemyY[i] + TILE_SIZE)
                     && enemyY[i] <= (playerY + TILE_SIZE)) {

                  score -= 10;

                  if (enemyType[i] >= ENEMY_TERMINATOR) {
                     terminatorTimer = 0;
                  }

                  if (enemyType[i] == ENEMY_CONFUSER) {
                     confused = 400;
                  } else if (enemyType[i] == ENEMY_NARROWER) {
                     narrowTimer = 400;
                  } else if (enemyType[i] == POWERUP_HEALTH) {
                     health = 5;
                  } else if (enemyType[i] == POWERUP_SCORE) {
                     score += 500;
                  } else if (enemyType[i] == POWERUP_BOMB) {
                     for (b = 0; b < numberOfEnemies; b += 1) {
                        enemyY[b] = -(random.nextInt(350) + 350);
                     }

                     blackHoleinPlace = NO;
                  } else {
                     health -= 1;
                  }

                  enemyY[i] = 800;

                  a = 0;
                  // Set up the explosion
                 for (b = 0; b < MAX_NUMBER_OF_PARTICLES - 1; b += 1) {
                     // Check if the particle is free
                    if (particleLife[b] == 0) {
                        particleX[b] = playerX;
                        particleY[b] = playerY;
                        particleVelocityX[b] = random.nextInt(180) - 90;
                        particleVelocityY[b] = random.nextInt(180) - 90;
                        particleLife[b] = 100;

                        a += 1;

                        if (a == NUMBER_OF_PARTICLES_IN_EXPLOSION) {
                           break;
                        }
                     }
                  }

                  // If the player has no health, then it's game over
                 if (health <= 0) {
                     state = STATE_GAMEOVER;
                     confused = 0;
                     narrowTimer = 0;
                     isHit = 0;
                     isPower = 0;
                     scoreLimit = 30;
                     currentPlanetIndex = 0;
                     playerVelocityX = 0;
                     playerVelocityY = 0;
                     score += 10; // This is a quick fix
                 } else {
                     if (enemyType[i] <= POWERUP_HEALTH) {
                        isPower = 25;
                     } else {
                        isHit = 25;
                     }
                  }
               }
            }
         }

         flickerCounter -= 2;
         if (flickerCounter <= 0) {
            flickerCounter = 100;
         }

         if (state == STATE_RUNNING) {
            // If there is a terminator, decrease the terminator timer.
           if (terminatorTimer > 0) {
               terminatorTimer -= 1;
            }

            if (powerupTimer > 0) {
               powerupTimer -= 1;
            }

            if (isHit > 0) {
               isHit -= 1;
            }

            if (isPower > 0) {
               isPower -= 1;
            }

            if (confused > 0) {
               confused -= 1;
            }

            if (narrowTimer > 0) {
               narrowTimer -= 1;

               if (TILE_SIZE < 32) {
                  TILE_SIZE += 1;
                  TILE_SIZE_QUARTER = TILE_SIZE / 4;
               }
            } else {
               if (TILE_SIZE > 16) {
                  TILE_SIZE -= 1;
                  TILE_SIZE_QUARTER = TILE_SIZE / 4;
               }
            }

            // Time to complete the level
           if (timeBeforePlanet > 0) {
               timeBeforePlanet -= 1;

               // The level is completed
              if (timeBeforePlanet == 0) {
                  state = STATE_LEVELCOMPLETED;

                  if (numberOfEnemies < MAX_NUMBER_OF_ENEMIES - 1) {
                     numberOfEnemies += 1;

                     enemyY[numberOfEnemies - 1] = 800;
                  }
                  playerVelocityX = 0;
                  playerVelocityY = -(PLAYER_SPEED * 2);
               }
            }
         }

         do {
            if (state == STATE_RUNNING) {
               // Detect keys
              if ((KEY_LEFT == YES && confused == 0)
                     || (KEY_RIGHT == YES && confused > 0)) {
                  playerVelocityX = -PLAYER_SPEED;
               } else if ((KEY_RIGHT == YES && confused == 0)
                     || (KEY_LEFT == YES && confused > 0)) {
                  playerVelocityX = PLAYER_SPEED;
               }
               if ((KEY_DOWN == YES && confused == 0)
                     || (KEY_UP == YES && confused > 0)) {
                  playerVelocityY = PLAYER_SPEED;
               } else if ((KEY_UP == YES && confused == 0)
                     || (KEY_DOWN == YES && confused > 0)) {
                  playerVelocityY = -PLAYER_SPEED;
               }
            }

            if (KEY_SPACE == YES) {
               if (state == STATE_TITLE || state == STATE_GAMEOVER) {
                  state = STATE_START;
               } else if (state == STATE_BREIFING) {
                  // Start a new level
                 state = STATE_RUNNING;

                  // Set up player
                 playerX = 160;
                  playerY = 385;
                  playerVelocityX = 0;
                  playerVelocityY = 0;
                  health = 5;

                  // Set up enemies
                 enemyX = new int[MAX_NUMBER_OF_ENEMIES];
                  enemyY = new int[MAX_NUMBER_OF_ENEMIES];
                  enemyDirection = new int[MAX_NUMBER_OF_ENEMIES];
                  enemyType = new int[MAX_NUMBER_OF_ENEMIES];
                  enemyY[0] = 800;

                  confused = 0;
                  narrowTimer = 0;
                  isHit = 0;
                  isPower = 0;
                  blackHoleinPlace = NO;
                  timeBeforePlanet = 3000 + (level * 500);

                  sunY = -300;
               }

               KEY_SPACE = NO;
            }

            if (state == STATE_RUNNING) {
               // Reduce player velocity
              if (playerVelocityX > 0) {
                  playerVelocityX -= 10;
               } else if (playerVelocityX < 0) {
                  playerVelocityX += 10;
               }
               if (playerVelocityY > 0) {
                  playerVelocityY -= 10;
               } else if (playerVelocityY < 0) {
                  playerVelocityY += 10;
               }

               // Black hole!
              if (blackHoleinPlace == YES) {
                  if (playerX < 160) {
                     if (playerVelocityX < 220) {
                        playerVelocityX += 16;
                     }
                  } else if (playerVelocityX > -220) {
                     playerVelocityX -= 16;
                  }

                  if (playerY < 240) {
                     playerVelocityY += 11;
                  } else {
                     playerVelocityY -= 11;
                  }
               }
            }

            if ((playerVelocityX < 0 && playerX >= 16)
                  || (playerVelocityX > 0 && playerX <= 302)) {
               playerX += (playerVelocityX / 50);
            } else {
               playerVelocityX = 0;
            }

            if ((playerVelocityY < 0 && playerY >= 10)
                  || (playerVelocityY > 0 && playerY <= 460)
                  || state == STATE_LEVELCOMPLETED) {
               playerY += (playerVelocityY / 50);
            } else {
               playerVelocityY = 0;
            }

            if (state == STATE_LEVELCOMPLETED && playerY < -200) {
               confused = 0;

               level += 1;
               currentPlanetIndex = random.nextInt(6);
               confused = 0;
               narrowTimer = 0;
               isHit = 0;
               isPower = 0;
               state = STATE_BREIFING;
            }

            // Move stars
           starsY += STAR_SPEED;
            starsX -= (playerVelocityX / 100);
            sunX -= (playerVelocityX / 100);
            sunY += SUN_SPEED;

            if (starsY == WINDOW_HEIGHT) {
               starsY = 0;
            }
            if (sunY > WINDOW_HEIGHT) {
               sunY = -300;
               sunX = random.nextInt(WINDOW_WIDTH);
            }

            // Update particles
           for (i = 0; i < MAX_NUMBER_OF_PARTICLES - 1; i += 1) {
               if (particleLife[i] > 0) {
                  particleLife[i] -= 1;

                  particleX[i] += particleVelocityX[i] / 10;
                  particleY[i] += particleVelocityY[i] / 10;

                  if (particleVelocityY[i] > 0) {
                     particleVelocityY[i] -= 1 / 2;
                  } else if (particleVelocityY[i] < 0) {
                     particleVelocityY[i] += 1 / 2;
                  }
                  if (particleVelocityX[i] > 0) {
                     particleVelocityX[i] -= 1 / 2;
                  } else if (particleVelocityX[i] < 0) {
                     particleVelocityX[i] += 1 / 2;
                  }

                  // If the particle is outside the screen, then set it as
                 // inactive
                 if ((particleX[i] > WINDOW_HEIGHT || particleX[i] < 0)
                        && (particleY[i] > WINDOW_HEIGHT || particleY[i] < 0)) {
                     particleLife[i] = 0;
                  }
               }
            }

            // Move enemies
           if (state == STATE_RUNNING) {
               for (i = 0; i < numberOfEnemies; i += 1) {
                  enemyX[i] -= (playerVelocityX / 100);

                  // Straight moving enemies and powerups
                 if (enemyType[i] == ENEMY_STRAIGHT
                        || enemyType[i] <= POWERUP_HEALTH) {
                     enemyY[i] += ENEMY_SPEED_Y;
                  }

                  // Bouncing enemies
                 else if (enemyType[i] == ENEMY_BOUNCING) {
                     if (enemyDirection[i] == LEFT) {
                        enemyX[i] -= ENEMY_SPEED_Y;

                        if (enemyX[i] <= 0) {
                           enemyDirection[i] = RIGHT;
                        }
                     } else {
                        enemyX[i] += ENEMY_SPEED_Y;

                        if (enemyX[i] >= 290) {
                           enemyDirection[i] = LEFT;
                        }
                     }

                     enemyY[i] += ENEMY_SPEED_X;
                  }

                  // Homing enemies
                 else if (enemyType[i] == ENEMY_HOMING) {
                     enemyY[i] += ENEMY_SPEED_Y;

                     if (playerX < enemyX[i]) {
                        enemyX[i] -= 2.;
                     } else if (playerX > enemyX[i]) {
                        enemyX[i] += 2;
                     }
                  }

                  else if (enemyType[i] == ENEMY_BLACKHOLE) {
                     if (terminatorTimer > 0) {
                        if (enemyY[i] < 240) {
                           enemyY[i] += 1;
                        } else {
                           blackHoleinPlace = YES;
                        }

                        if (enemyX[i] < 160) {
                           enemyX[i] += 1;
                        } else if (enemyX[i] > 160) {
                           enemyX[i] -= 1;
                        }
                     } else {
                        enemyY[i] += ENEMY_SPEED_Y;
                        blackHoleinPlace = NO;
                     }
                  }

                  // Terminator, confuser- and narrower-enemies
                 else {
                     if (playerX < enemyX[i]) {
                        enemyX[i] -= 1;
                     } else if (playerX > enemyX[i]) {
                        enemyX[i] += 1;
                     }

                     if (terminatorTimer > 0) {
                        if (playerY < enemyY[i]) {
                           enemyY[i] -= 1;
                        } else if (playerY > enemyY[i]) {
                           enemyY[i] += 1;
                        }
                     } else {
                        enemyY[i] += ENEMY_SPEED_Y;
                     }
                  }
               }
            }

            // Enemy animation
           animationCounter += 1;
            if (animationCounter == 10) {
               if (animationEnlarge == YES) {
                  animationFactor += 1;

                  if (animationFactor >= TILE_SIZE_QUARTER) {
                     animationEnlarge = NO;
                  }
               } else {
                  animationFactor -= 1;

                  if (animationFactor <= -TILE_SIZE_QUARTER) {
                     animationEnlarge = YES;
                  }
               }

               animationCounter = 0;
            }
           
            nextFrameStartTime += 16666667;
         } while (nextFrameStartTime < System.nanoTime());

         // Update the player position arrays, so we can draw the spaceship
        a = playerVelocityX / 60;
         playerXPoints[0] = playerX + a;
         playerXPoints[1] = playerX - (TILE_SIZE_QUARTER * 2 + a);
         playerXPoints[2] = (playerX + TILE_SIZE_QUARTER * 2 - a);
         playerYPoints[0] = playerY;
         playerYPoints[2] = playerY + TILE_SIZE;
         playerYPoints[1] = (playerYPoints[2] - a);

         g.setColor(Color.BLACK);
         g.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);

         // Draw stars
        if (!((confused > 0 || narrowTimer > 0) && flickerCounter > 50)) {
            g.drawImage(starImage, starsX, starsY, null);
            g.drawImage(starImage, starsX, starsY - WINDOW_HEIGHT, null);
         }

         g.drawImage(sunImage, sunX, sunY, null);

         // Draw stuff
        if (isHit > 0) {
            g.setColor(Color.RED);
            g.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
         } else if (isPower > 0) {
            g.setColor(Color.GREEN);
            g.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
         } else if (confused > 0 && flickerCounter > 50) {
            g.setColor(Color.YELLOW);
            g.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
         } else if (narrowTimer > 0 && flickerCounter > 50) {
            g.setColor(Color.PINK);
            g.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
         }

         g.setColor(Color.WHITE);

         // Draw particles
        for (i = 0; i < MAX_NUMBER_OF_PARTICLES - 1; i += 1) {
            if (particleLife[i] > 0) {
               a = 55 + (particleLife[i] * 2);

               g.setColor(new Color(a, a, a));
               g.fillOval(particleX[i], particleY[i], TILE_SIZE_QUARTER,
                     TILE_SIZE_QUARTER);
            }
         }

         // Draw on state running
        if (state == STATE_RUNNING || state == STATE_LEVELCOMPLETED) {
            // Draw player
           g.setColor(Color.GREEN);
            g.fillPolygon(playerXPoints, playerYPoints, 3);

            // Draw enemies
           for (i = 0; i < numberOfEnemies; i += 1) {
               if (enemyType[i] == ENEMY_STRAIGHT) {
                  g.setColor(Color.MAGENTA);
               }

               else if (enemyType[i] == ENEMY_BOUNCING) {
                  g.setColor(Color.CYAN);
               }

               else if (enemyType[i] == ENEMY_HOMING) {
                  g.setColor(Color.RED);
               }

               else if (enemyType[i] == ENEMY_TERMINATOR) {
                  g.setColor(Color.DARK_GRAY);
               }

               else if (enemyType[i] == ENEMY_CONFUSER) {
                  g.setColor(Color.YELLOW);
               }

               else if (enemyType[i] == ENEMY_NARROWER) {
                  g.setColor(Color.PINK);
               }

               else if (enemyType[i] <= POWERUP_HEALTH) {
                  g.setColor(Color.GREEN);

                  if (enemyType[i] == POWERUP_HEALTH) {
                     g.drawString("HEALTH", enemyX[i]
                           - (TILE_SIZE_QUARTER * 3), enemyY[i]
                           + (TILE_SIZE * 2));
                  } else if (enemyType[i] == POWERUP_SCORE) {
                     g.drawString("POINTS", enemyX[i]
                           - (TILE_SIZE_QUARTER * 3), enemyY[i]
                           + (TILE_SIZE * 2));
                  } else if (enemyType[i] == POWERUP_BOMB) {
                     g.drawString("BOMB!!", enemyX[i]
                           - (TILE_SIZE_QUARTER * 3), enemyY[i]
                           + (TILE_SIZE * 2));
                  }
               }

               if (enemyType[i] == ENEMY_BLACKHOLE) {
                  g.setColor(Color.BLACK);
                  g.fillOval(enemyX[i], enemyY[i], TILE_SIZE
                        + animationFactor, TILE_SIZE + animationFactor);

                  g.setColor(Color.WHITE);
                  g.drawOval(enemyX[i], enemyY[i], TILE_SIZE
                        + animationFactor, TILE_SIZE + animationFactor);
               } else {
                  g.fillOval(enemyX[i], enemyY[i], TILE_SIZE
                        + animationFactor, TILE_SIZE + animationFactor);
               }
            }
         }

         if (state == STATE_RUNNING || state == STATE_LEVELCOMPLETED
               || state == STATE_GAMEOVER) {
            // Draw texts
           if ((confused > 0 || narrowTimer > 0) && flickerCounter > 50) {
               g.setColor(Color.BLACK);
            } else {
               g.setColor(Color.WHITE);
            }

            if (state != STATE_GAMEOVER && timeBeforePlanet != 0
                  && (timeBeforePlanet / 100) <= 1 && flickerCounter > 50) {
               g.drawString("Going in for landing on "
                     + planets[currentPlanetIndex] + ".", 60, 200);
            }

            g.drawString("Score: " + score, 10, 419);

            g.drawString("Health:", 10, 437);
            for (i = 0; i < health; i += 1) {
               g.fillOval(60 + (12 * i), 428, 8, 8);
            }

            g.drawString("Pkgs delivered: " + level, 10, 455);
            g.drawString("Distance to " + planets[currentPlanetIndex]
                  + ": " + (timeBeforePlanet / 100), 10, 473);
         }

         else if (state == STATE_BREIFING) {
            g.setColor(Color.WHITE);

            if (level == 0) {
               g.drawString("Hi package delivering hero!", 45, 120);
               g.drawString("You need to deliver a very secret", 45, 150);
            } else {
               g.drawString("Well done! The package is now safe.", 45, 120);
               g.drawString("Now you need to deliver another secret", 45,
                     150);
            }

            if (flickerCounter > 50) {
               g.drawString("Press space to start mission.", 45, 250);
            }

            g.drawString("package to our base on "
                  + planets[currentPlanetIndex] + ".", 45, 170);
         }

         // Draw on state title
        else if (state == STATE_TITLE) {
            g.drawString("Legend of the package delivering hero", 45, 200);

            if (flickerCounter > 50) {
               g.drawString("Press space to start", 100, 250);
            }
         }

         // Draw on state game over
        if (state == STATE_GAMEOVER) {
            g.setColor(Color.WHITE);
            g.drawString("GAME OVER", 127, 210);

            if (flickerCounter > 50) {
               g.drawString("Press space to restart.", 100, 250);
            }
         }

         // Draw the entire results on the screen.
        appletGraphics.drawImage(screen, 0, 0, null);

         // Burn off extra cycles
        long remaining = nextFrameStartTime - System.nanoTime();
         if (remaining > 0) {
            try {
               Thread.sleep(remaining / 1000000);
            } catch (Exception e) {
            }
         }
      }
   }

   /**
    * Check for key events
    */

   public void processKeyEvent(KeyEvent e) {
      int keyCode = e.getKeyCode();
      if (e.getID() == KeyEvent.KEY_PRESSED) {
         if (keyCode == KeyEvent.VK_LEFT) {
            KEY_LEFT = YES;
         } else if (keyCode == KeyEvent.VK_RIGHT) {
            KEY_RIGHT = YES;
         } else if (keyCode == KeyEvent.VK_UP) {
            KEY_UP = YES;
         } else if (keyCode == KeyEvent.VK_DOWN) {
            KEY_DOWN = YES;
         } else if (keyCode == KeyEvent.VK_SPACE) {
            KEY_SPACE = YES;
         }
      } else if (e.getID() == KeyEvent.KEY_RELEASED) {
         if (keyCode == KeyEvent.VK_LEFT) {
            KEY_LEFT = NO;
         } else if (keyCode == KeyEvent.VK_RIGHT) {
            KEY_RIGHT = NO;
         } else if (keyCode == KeyEvent.VK_UP) {
            KEY_UP = NO;
         } else if (keyCode == KeyEvent.VK_DOWN) {
            KEY_DOWN = NO;
         }
      }
   }
}
Offline ctomni231

JGO Wizard


Medals: 99
Projects: 1
Exp: 7 years


Not a glitch. Just have a lil' pixelexia...


« Reply #1 - Posted 2013-01-13 00:45:36 »

I am just doing the basic sleep in my code...

1  
2  
3  
4  
5  
6  
7  
try {
       Thread.sleep(10);
} catch (Exception e) {
}
           
if(!isActive())
      return;


I haven't had any real problems with frame rate. (You can test to see how it runs by trying it.) Older computers always have a much slower frame rate for Applets by my experiences, but they usually run okay when dealing with JFrames.

Offline moogie

JGO Knight


Medals: 12
Projects: 6
Exp: 10 years


Java games rock!


« Reply #2 - Posted 2013-01-13 03:03:38 »

Can you give an example of an "older" system that presents the issues? I have started 10 parallel instances and there was no slower frame rates.... but that said, if this is for java 4k then you should really only care about making sure that it will work well with JRE7 and hardware that most people would have... i guess one would look at Steam's statistics for that info.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline pjt33
« Reply #3 - Posted 2013-01-13 08:36:14 »

I had a quick skim and there's no obvious need for regular garbage collection - Event objects will be generated by AWT, but they're small. You could try running with -verbose:gc just to check that.

The other obvious step for some non-intrusive profiling is to print remaining to System.out. Are some frames taking longer than the allocated time, or is the problem in the waiting?
Offline Jens_S
« Reply #4 - Posted 2013-01-13 14:33:48 »

I am just doing the basic sleep in my code...

1  
2  
3  
4  
5  
6  
7  
try {
       Thread.sleep(10);
} catch (Exception e) {
}
           
if(!isActive())
      return;


I haven't had any real problems with frame rate. (You can test to see how it runs by trying it.) Older computers always have a much slower frame rate for Applets by my experiences, but they usually run okay when dealing with JFrames.

I'm pretty sure that the issue have nothing to do with the timing code. I've tried with different kind of timing strategies, but the problem still remains. Sad
Offline Jens_S
« Reply #5 - Posted 2013-01-13 14:34:57 »

Can you give an example of an "older" system that presents the issues? I have started 10 parallel instances and there was no slower frame rates.... but that said, if this is for java 4k then you should really only care about making sure that it will work well with JRE7 and hardware that most people would have... i guess one would look at Steam's statistics for that info.

Both computer have Intel Core2 Duo processors and 2GB ram. Both are using cheap build in graphic cards. They are not really old, but it' no state-of-the-art machine. Still, I feel they should be good enough to run a simple Java applet game.

One the Windows laptop the game is still playable, but the framerate is bad and the animation is not very smooth. The experience on the Linux box is both better and worse - the framerate is much smoother, but every now and then there are short freeze-moments. I usually associate such freezing-moments with the garbage collector, but I can't see any reason for the GC to kick in (since I'm not allocating very many object).
Offline Jens_S
« Reply #6 - Posted 2013-01-13 14:52:55 »

I had a quick skim and there's no obvious need for regular garbage collection - Event objects will be generated by AWT, but they're small. You could try running with -verbose:gc just to check that.

The other obvious step for some non-intrusive profiling is to print remaining to System.out. Are some frames taking longer than the allocated time, or is the problem in the waiting?

Thanks for the tips about running with -verbose:gc! The gc kicks in from time to time, but there seems to be no connection with the freezing-moments.

I've tried to print the "remaining"-value, on both computer. On my main computer (where it all work fine), there is a very small variation between the time frames. On the "slower" computers the variation is bigger, but I can't see a straight correlation between the variation and the stuttering.

To diagnose the problem I've tried to remove almost all the code, and just keeping the scrolling stars, but the problem still remains on the two computer:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
import java.applet.Applet;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.Random;

public class G extends Applet implements Runnable {
   public void start() {
      new Thread(this).start();
   }

   public void run() {
      setSize(320, 480);
      BufferedImage screen = new BufferedImage(320, 480,
            BufferedImage.TYPE_INT_RGB);
      Graphics g = screen.getGraphics();
      Graphics appletGraphics = getGraphics();
      Random random = new Random();

      int a = 0;
      int starsX = -100;
      int starsY = 0;

      // Create star image
     BufferedImage starImage = new BufferedImage(320 + 200, 480,
            BufferedImage.TYPE_INT_RGB);
      Graphics starGfx = starImage.getGraphics();
      for (int i = 0; i < 200; i++) {
         a = random.nextInt(200);
         starGfx.setColor(new Color(250 - a, 250 - a, 250 - a));
         starGfx.fillOval(random.nextInt(320 + 200), random.nextInt(480), 2, 2);
      }

      // Game loop.
     while (true) {
         // Move stars
        starsY += 1;
         if (starsY == 320) {
            starsY = 0;
         }

         // Draw stars
        g.drawImage(starImage, starsX, starsY, null);

         // Draw the entire results on the screen.
        appletGraphics.drawImage(screen, 0, 0, null);

         // Burn off extra cycles
        try {
            Thread.sleep(10);
         } catch (InterruptedException e) {
         }
      }
   }
}


I've also tried to replace to replace the timing code with a more busy timing loop, but the problem still remains:
1  
2  
3  
4  
long nextFrameStartTime = System.nanoTime() + 1666667;
while (System.nanoTime() < nextFrameStartTime) {
  Thread.yield();
}


And also an extremely greedy timing solution, without any sleeping/yielding at all. This solutions makes the animation more smooth, but the freezing/stuttering still seems to occur:
1  
2  
long nextFrameStartTime = System.nanoTime() + 1666667;
while (System.nanoTime() < nextFrameStartTime) {}      


So the issue is not related to the application logic, not to the rendering and not to the timing...  Huh

Am I doing something incredibly wrong, or is there something terribly wrong with my computer (most likely I'm doing something wrong  Wink).

The Linux box is running OpenJDK, but the game is running fine with OpenJDK on my main computer. The windows laptop is running the official Java 6 from Oracle, and the official browser plugin for IE. In Chrome everything works fine for some reason.
Offline pjt33
« Reply #7 - Posted 2013-01-13 15:33:33 »

I've tried to print the "remaining"-value, on both computer. On my main computer (where it all work fine), there is a very small variation between the time frames. On the "slower" computers the variation is bigger, but I can't see a straight correlation between the variation and the stuttering.
If it doesn't go negative at all then that rules out one important candidate problem.

I'm out of relatively sensible ideas. The more outlandish ones would include using renice on the Linux box to see whether it's a scheduling issue; disconnecting from the network to eliminate some interrupts; disabling antivirus on the Windows box; and using fullscreen exclusive mode to limit the other traffic to the graphics card. But I'm not particularly bullish about any of those.
Offline moogie

JGO Knight


Medals: 12
Projects: 6
Exp: 10 years


Java games rock!


« Reply #8 - Posted 2013-01-13 22:08:40 »

Probably a silly suggestion, especially for a java 4k game, but have you tried promoting the priority of java process running your game? Perhap your OS is being a little to sparing to the process?
Offline Jens_S
« Reply #9 - Posted 2013-01-14 17:35:03 »

I've tried to print the "remaining"-value, on both computer. On my main computer (where it all work fine), there is a very small variation between the time frames. On the "slower" computers the variation is bigger, but I can't see a straight correlation between the variation and the stuttering.
If it doesn't go negative at all then that rules out one important candidate problem.

I'm out of relatively sensible ideas. The more outlandish ones would include using renice on the Linux box to see whether it's a scheduling issue; disconnecting from the network to eliminate some interrupts; disabling antivirus on the Windows box; and using fullscreen exclusive mode to limit the other traffic to the graphics card. But I'm not particularly bullish about any of those.

I've seen the "remaining" value go negative a few times, but I can see no connection between the negative values and the freezing.

Since the problem seems to occur even if I run the program with just the bare minimums, and since it works fine on most computers, I guess that I have to ignore this problem. I've spent to much time already on this issue. I'll upload the game to Java4k wait for feedback - if everyone complains about performance issues I have to take another look.

Thanks for your suggestions, and thanks for taking time to look at the code!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Jens_S
« Reply #10 - Posted 2013-01-14 17:41:25 »

Probably a silly suggestion, especially for a java 4k game, but have you tried promoting the priority of java process running your game? Perhap your OS is being a little to sparing to the process?

There must be something weird going on with the Linux box. I see serious stuttering even if I remove all application logic, all timing code and almost all rendering code. The framerate is not perfect on the Windows laptop (in IE; it runs fine in Chrome), but the game is still playable. I'll upload the game to Java4k wait for feedback - if everyone complains about performance issues I have to take another look.

Thanks for your input!
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

BurntPizza (25 views)
2014-09-19 03:14:18

Dwinin (39 views)
2014-09-12 09:08:26

Norakomi (68 views)
2014-09-10 13:57:51

TehJavaDev (93 views)
2014-09-10 06:39:09

Tekkerue (47 views)
2014-09-09 02:24:56

mitcheeb (68 views)
2014-09-08 06:06:29

BurntPizza (51 views)
2014-09-07 01:13:42

Longarmx (38 views)
2014-09-07 01:12:14

Longarmx (44 views)
2014-09-07 01:11:22

Longarmx (40 views)
2014-09-07 01:10:19
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!