12 Replies Latest reply: Oct 4, 2011 11:30 PM by 875749 RSS

    My Attempt at Active Rendering is Very Slow?

    875749
      Hey, guys! I finally got together my scrolling tile engine for the game I'm working on. I first implemented it with passive rendering, not knowing anything about active rendering, and it turned out very slow. After getting some pointers about active rendering, I reimplemented the engine using active rendering.

      However, it's still running just as slow! I'm not sure if I missed something somewhere, but I would appreciate if someone could take a look and see if I messed up my implementation of active rendering. I pretty much used everything straight out of the Java Tutorials and a gamedev.net article, using a BufferStrategy, turning off repaint, and some other items. I will include the relevant classes below.

      Basically, the LevelRenderer class inherits a JFrame, creates a full-screen GraphicsEnvironment for itself, handles input to update the level and the player, and handles the BufferStrategy and the other drawing-related tasks in its run method, which is called from main() in another class called GameTest. The LevelRenderer creates a Player and Level object, each of which has its own draw routine. Lastly, the GameTest class just creates a LevelRenderer object and then calls its run method, which takes everything from there.

      Thank you guys so much!

      Here's the LevelRenderer class that inherits from a JFrame and implements the rendering:
      /* This class's job is to manage a Player and Level object and call their render and update routines. */
       
      import java.awt.*;
      import java.awt.event.*;
      import java.awt.image.*;
      import java.io.*;
      import javax.imageio.*;
      import javax.swing.JFrame;
      import javax.swing.*;
      import java.util.Random;
      import java.awt.Color;
      
      public class LevelRenderer extends JFrame
      {   
          //
          // CONSTANTS
          //
          
          private final int TILE_SIZE = 14;
          private final int SCREEN_WIDTH = 1280;
          private final int SCREEN_HEIGHT = 768;
          
          //
          // END OF CONSTANTS
          //
          
          // will be used as a buffer before everything is drawn to the screen
          private BufferedImage buffer2;
          
          // back buffer
          private BufferStrategy buffer;
          
          // character object
          private Player myPlayer;
          
          // level object
          private Level myLevel;
          
          // screen object
          private Screen s;
          
          // graphics object of the buffer
          private Graphics gr;
          
          // Graphics object for the buffer strategy
          private Graphics graphics;
          
          // boolean to determine when to end the game
          private boolean endGame;
          
          // CONSTRUCTOR
          public LevelRenderer()
          {
              setPreferredSize(new Dimension(1280, 768));
              setIgnoreRepaint( true );
              setUndecorated( true );
      
              setFocusable(true);
              requestFocus();
              
              setResizable(false);
              
              addKeyListener( new KeyAdapter() 
              {
                  public void keyPressed(KeyEvent e)
                  { 
                      processKey(e);  
                  }
                  
                  public void keyReleased(KeyEvent e)
                  {
                      processRelease(e);
                  }
              });
              
              buffer2 = new BufferedImage(1280, 768, BufferedImage.TYPE_INT_ARGB);
              
              buffer2.createGraphics();
              gr = buffer2.getGraphics();
              
              myPlayer = new Player();
              myLevel = new Level("obstaclemap");
              
              endGame = false;
          }
          
          // method to simply load an image from a path
          public static BufferedImage loadImage(String ref)
          {
              BufferedImage bimg = null;
                 
              try
              {
                 bimg = ImageIO.read(new File(ref));
              }
              catch (Exception e)
              {
                  e.printStackTrace();
              }
             
              return bimg;
          }
          
          // Run method for class
          public void run(DisplayMode dm)
           {     
              setBackground(Color.WHITE);
                s = new Screen();
              s.setFullScreen(dm, this);
              
              this.createBufferStrategy( 2 );
              buffer = this.getBufferStrategy();
      
              while (!endGame)
              {
                  try
                  {   
                      // clear back buffer...
                      gr = buffer2.createGraphics();
                      gr.setColor(Color.BLACK);
                      
                      // edit player and level
                      myLevel.renderLevel();
                      myPlayer.animatePlayer();
                      myLevel.drawLevel(gr, 0, 0);
                      myPlayer.drawPlayer(gr, (SCREEN_WIDTH / 2) - TILE_SIZE / 2, (SCREEN_HEIGHT / 2) - TILE_SIZE);
                      
                      graphics = buffer.getDrawGraphics();
                      graphics.drawImage(buffer2, 0, 0, null);
                      
                      if( !buffer.contentsLost() )
                      {
                          buffer.show();
                      }
                  }
                  catch (Exception ex) 
                  { 
                      System.err.println("Game Update Error: " + ex);
                  }
              }
              
                s.restoreScreen();
           } 
          
          // method to handle inputs and adjust the player accordingly
          public void processKey(KeyEvent e)
          {
              int keyCode = e.getKeyCode();
              boolean moved = false;
              int xDisplace, yDisplace;
              
              // termination key
              if (keyCode == KeyEvent.VK_ESCAPE)
              {
                  endGame = true;
              }
              
              // 0 - up
              // 1 - left
              // 2 - right
              // 3 - down
              // 4 - jump
              
              if (keyCode == KeyEvent.VK_UP)
              {
                  myPlayer.updatePlayer(0);
                  myLevel.updateLevel(0);
              }
              if (keyCode == KeyEvent.VK_LEFT)
              {
                  myPlayer.updatePlayer(1);
                  myLevel.updateLevel(1);
              }
              if (keyCode == KeyEvent.VK_RIGHT)
              {
                  myPlayer.updatePlayer(2);
                  myLevel.updateLevel(2);
              }
              if (keyCode == KeyEvent.VK_DOWN)
              {
                  myPlayer.updatePlayer(3);
                  myLevel.updateLevel(3);
              }
              if (keyCode == KeyEvent.VK_SPACE)
              {
                  myPlayer.updatePlayer(4);
                  myLevel.updateLevel(4);
              }
          }
          
          // method to handle inputs and adjust the player accordingly
          public void processRelease(KeyEvent e)
          {
              int keyCode = e.getKeyCode();
              boolean moved = false;
              int xDisplace, yDisplace;
              
              // 0 - up
              // 5 - left
              // 6 - right
              // 3 - down
              // 4 - jump
              
              if (keyCode == KeyEvent.VK_UP)
              {
                  myPlayer.updatePlayer(0);
              }
              if (keyCode == KeyEvent.VK_LEFT)
              {
                  myPlayer.updatePlayer(5);
              }
              if (keyCode == KeyEvent.VK_RIGHT)
              {
                  myPlayer.updatePlayer(6);
              }
              if (keyCode == KeyEvent.VK_DOWN)
              {
                  myPlayer.updatePlayer(3);
              }
              if (keyCode == KeyEvent.VK_SPACE)
              {
                  myPlayer.updatePlayer(4);
              }
          }
      }
      Here's the Player class that represents the player and his current animation:
      /* This class's purpose will be to store the data of the player character for movement and appearance. It will also
       * take input. The player image will be created as a sheet of animation frames and split by the class. */
       
      import java.awt.image.*;
      import java.io.*;
      import javax.imageio.*;
      import java.awt.*;
       
      public class Player
      {
          //
          // CONSTANTS
          //
          
          private final int TILE_SIZE = 14;
          private final int SCREEN_WIDTH = 1280;
          private final int SCREEN_HEIGHT = 768;
          
          //
          // END OF CONSTANTS
          //
          
          // image to store the player's frames of animation as a sheet/loaded first
          private BufferedImage playerSheet;
          
          // image array to store the individual frames of animation/split by program
          private BufferedImage playerFrames[];
          
          // index used to represent the current frame to draw on the screen of the player
          private int currentIndex = 0;
          
          // enum representing the player's state of movement for animation
          private enum PlayerState {STILL_LEFT, STILL_RIGHT, MOVE_LEFT, MOVE_RIGHT, JUMP}
          
          // variable used to represent the player's current animation state
          private PlayerState currentState;
          
          // variable to keep track of last direction the character was facing when going back to still
          private PlayerState lastState;
          
          // long used to represent the system time, used as a timer
          private long movementTimer;
          
          // long used to represent the previously used time as a timer
          private long stillTimer;
          
          // CONSTRUCTOR
          public Player()
          {
              playerSheet = makeColorTransparent("playersheet1.png", 0xFFFF65F6);
              playerFrames = splitImage(playerSheet, 4, 2);
              movementTimer = System.nanoTime();
              stillTimer = movementTimer;
              currentState = PlayerState.STILL_LEFT;
              lastState = PlayerState.STILL_LEFT;
          }
          
          // this method will draw to whatever graphics context is passed to the method (game window)
          public void drawPlayer(Graphics gr, int x, int y)
          {
              gr.drawImage(playerFrames[currentIndex], x, y, null);
          }
          
          // method to simply load an image from a path
          private static BufferedImage loadImage(String ref)
          {
              BufferedImage bimg = null;
                 
              try
              {
                 bimg = ImageIO.read(new File(ref));
              }
              catch (Exception e)
              {
                  e.printStackTrace();
              }
             
              return bimg;
          }
          
          // method to create a tile array for tile sets
          private BufferedImage[] splitImage(BufferedImage img, int cols, int rows)
          {
              int w = img.getWidth() / cols;
              int h = img.getHeight() / rows;
              int num = 0;
              
              BufferedImage imgs[] = new BufferedImage[w * h];
              
              for (int y = 0; y < rows; y++)
              {
                  for (int x = 0; x < cols; x++)
                  {
                      imgs[num] = new BufferedImage(w, h, img.getType());
                      
                      Graphics2D g = imgs[num].createGraphics();
                      g.drawImage(img, 0, 0, w, h, w * x, h * y, w * x + w, h * y + h, null);
                      g.dispose();
                      num++;
                  }
              }
              
              return imgs;
          }
          
          // image-loading method that will also alpha the color key for each tile
          public static BufferedImage makeColorTransparent(String ref, int color)
          {
              BufferedImage image = loadImage(ref);
              BufferedImage dimg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
              Graphics2D g = dimg.createGraphics();
              g.setComposite(AlphaComposite.Src);
              g.drawImage(image, null, 0, 0);
              g.dispose();
              
              for (int i = 0; i < dimg.getHeight(); i++)
              {
                  for (int j = 0; j < dimg.getWidth(); j++)
                  {
                      if (dimg.getRGB(j, i) == color)
                      {
                          dimg.setRGB(j, i, 0x8F1C1C);
                      }
                  }
              }
              
              return dimg;
          }
          
          // method to update the player based on user input
          public void updatePlayer(int input)
          {
              // update the still timer to manage when the last key press was
              stillTimer = System.nanoTime();
              
              switch (input)
              {
                  // up
                  case 0:
                      break;
                  // left
                  case 1:
                      if (currentState != PlayerState.MOVE_LEFT)
                      {
                          movementTimer = System.nanoTime();
                      }
                      currentState = PlayerState.MOVE_LEFT;
                      lastState = PlayerState.MOVE_LEFT;
                      break;
                  // right
                  case 2:
                      if (currentState != PlayerState.MOVE_RIGHT)
                      {
                          movementTimer = System.nanoTime();
                      }
                      currentState = PlayerState.MOVE_RIGHT;
                      lastState = PlayerState.MOVE_RIGHT;
                      break;
                  // down
                  case 3:
                      break;
                  // jump
                  case 4:
                      break;
                  
                  // still left
                  case 5:
                      currentState = PlayerState.STILL_LEFT;
                      lastState = PlayerState.STILL_LEFT;
                      break;
                  
                  // still right
                  case 6:
                      currentState = PlayerState.STILL_RIGHT;
                      lastState = PlayerState.STILL_RIGHT;
                      break;
              }
          }
          
          // method to manage the player's animation
          public void animatePlayer()
          {   
              switch (currentState)
              {
                  case STILL_LEFT:
                      currentIndex = 0;
                      break;
                  case STILL_RIGHT:
                      currentIndex = 4;
                      break;
                  case MOVE_LEFT:
                      // if set to a still frame, set it to start running left
                      if (currentIndex == 0 || currentIndex == 4)
                      {
                          currentIndex = 1;
                      }
                      // if a 300 nanosecond gap has passed, allow the next frame
                      if (System.nanoTime() - movementTimer > 100000000)
                      {
                          if (currentIndex == 1)
                          {
                              currentIndex = 2;
                          }
                          else
                          {
                              currentIndex = 1;
                          }
                          
                          movementTimer = System.nanoTime();
                      }
                      break;
                  case MOVE_RIGHT:
                      // if set to a still frame, set it to start running right
                      if (currentIndex == 0 || currentIndex == 4)
                      {
                          currentIndex = 5;
                      }
                      // if a 300 nanosecond gap has passed, allow the next frame
                      if (System.nanoTime() - movementTimer > 100000000)
                      {
                          if (currentIndex == 5)
                          {
                              currentIndex = 6;
                          }
                          else
                          {
                              currentIndex = 5;
                          }
                          
                          movementTimer = System.nanoTime();
                      }
                      break;
                  case JUMP:
                  
                      break;
              }
          }
      }
      Here's the Level class that represents a level after loading it from an image file and storing the tiles into an array:
      /* The purpose of this class will be to load and manage a level, including its camera. */
      
      import java.awt.image.*;
      import java.io.*;
      import javax.imageio.*;
      import java.awt.*;
      
      public class Level
      {
          //
          // CONSTANTS
          //
          
          private final int TILE_SIZE = 14;
          private final int SCREEN_WIDTH = 1280;
          private final int SCREEN_HEIGHT = 768;
          
          //
          // END OF CONSTANTS
          //
          
          // stores the pixel image of the current level
          private BufferedImage levelImage;
          
          // stores the width and height of the level
          private int width, height;
          
          // stores the name of the level
          private String levelName;
          
          // stores collision map for level
          private LevelCollisions myCollisions;
          
          // stores the tile types in an array as assigned by colors
          private int levelTiles[][];
          
          // image used as the sheet for the level's tiles
          private BufferedImage tileSheet;
          
          // image array used to store the different tiles
          private BufferedImage[] tiles;
          
          // the image which represents the current view of the level
          private BufferedImage cameraImage;
          
          // Graphics context of the camera image
          private Graphics cameraG;
          
          // variables to represent the level's offset from the top left corner while moving
          private int offsetX, offsetY;
          
          // variables to represent the level's pixel map coordinate
          private int coordX, coordY;
          
          // 
          // STATIC COLOR VARIABLES
          //
          
          private static final int SPACE_COLOR = 0xFF000000;
          private static final int WALL_COLOR = 0xFFFFFFFF;
          
          //
          // END OF STATIC COLOR VARIABLES
          //
          
          //
          // CONSTRUCTOR
          //
          public Level(String level)
          {
              // load level image and collision map
              levelName = level;
              levelImage = loadImage(level + ".png");
              myCollisions = new LevelCollisions(level + "Collision");
              levelTiles = loadLevel();   
              
              // create blank camera canvas
              cameraImage = new BufferedImage(1280, 768, BufferedImage.TYPE_INT_ARGB);
              cameraImage.createGraphics();
              cameraG = cameraImage.getGraphics();
              
              // offsets start at 0
              offsetX = offsetY = 0;
              
              // coordinate starts at bottom right
              coordX = 600;
              coordY = 383;
              
              // fill tile images
              tileSheet = loadImage("obstacletiles.png");
              tiles = splitImage(tileSheet, 2, 1);
              
              this.renderLevel();
          }
          
          // method to load the color values into an array
          public int[][] loadLevel()
          {
              height = levelImage.getHeight();
              width = levelImage.getWidth();
              
              int levelValues[][] = new int[width][height];
              
              // fill array with color values layer by layer
              for (int y = 0; y < height; y++)
              {
                  for (int x = 0; x < width; x++)
                  {
                      levelValues[x][y] = levelImage.getRGB(x, y);
                  }   
              }
              
              return levelValues;
          }
          
          // method to get the tile color from a given tile
          public int getTile(int x, int y)
          {
              return levelTiles[x][y];
          }
          
          // method to draw the current camera view of the level on the screen
          public void drawLevel(Graphics gr, int x, int y)
          {
              gr.drawImage(cameraImage, x, y, null);
          }
          
          // method to render the actual image before drawing it
          public void renderLevel()
          {
              // keeps track of graphics coordinate
              int x, y;
              
              // keeps track of tile to draw
              int tileX, tileY;
              
              tileY = coordY;
              
              // draw all the tiles based on offsets, layer by layer
              for (y = offsetY; y < SCREEN_HEIGHT + offsetY; y += TILE_SIZE)
              {
                  tileX = coordX;
                  for (x = offsetX; x < SCREEN_WIDTH + offsetX; x += TILE_SIZE)
                  {
                      // determine which tile to draw based on tile color in array
                      switch (this.getTile(tileX, tileY))
                      {
                          case SPACE_COLOR:
                              cameraG.drawImage(tiles[0], x, y, null);
                              break;
                              
                          case WALL_COLOR:
                              cameraG.drawImage(tiles[1], x, y, null);
                              break;
                      }
                      
                      tileX++;
                  }
                  
                  tileY++;
              }
              
              // steps to take in case of an offset
              if (offsetX > 0)
              {
              
              }
              
              if (offsetX < 0)
              {
              
              }
              
              if (offsetY < 0)
              {
              
              }
              
              if (offsetY > 0)
              {
              
              }
          }
          
          // method to update the level's current position for the camera
          public void updateLevel(int input)
          {
              switch (input)
              {
                  // up
                  case 0:
                      // update offset up if not too far up
                      if (coordY > 30)
                      {
                          offsetY += 2;
                      }   
                      
                      // if a tile length has been moved, then offset becomes 0 and coordY is decreased
                      if (offsetY >= TILE_SIZE)
                      {
                          offsetY = 0;
                          coordY--;
                      }
                      break;
                  // left
                  case 1:
                      // update offset to the left if not too far left
                      if (coordX > 30)
                      {
                          offsetX += 2;
                      }
                      
                      // if a tile length has been moved, then offset becomes 0 and coordX is decreased
                      if (offsetX >= TILE_SIZE)
                      {
                          offsetX = 0;
                          coordX--;
                      }
                      break;
                  // right
                  case 2:
                      // update offset to the right if not too far right
                      if (coordX < width - 30)
                      {
                          offsetX -= 2;
                      }
                      
                      // if a tile length has been moved, then offset becomes 0 and coordX is increased
                      if (offsetX <= -TILE_SIZE)
                      {
                          offsetX = 0;
                          coordX++;
                      }
                      break;
                  // down
                  case 3:
                      // update offset down if not too far down
                      if (coordY < height - 30)
                      {
                          offsetY -= 2;
                      }
                      
                      // if a tile legnth has been moved, then offset becomes 0 and coordY is increased
                      if (offsetY <= -TILE_SIZE)
                      {
                          offsetY = 0;
                          coordY++;
                      }
                      break;
                  // jump
                  case 4:
                      break;
              }
          }
          
          // method to simply load an image from a path
          public static BufferedImage loadImage(String ref)
          {
              BufferedImage bimg = null;
                 
              try
              {
                 bimg = ImageIO.read(new File(ref));
              }
              catch (Exception e)
              {
                  e.printStackTrace();
              }
             
              return bimg;
          }
          
          // method to create a tile array for tile sets
          public static BufferedImage[] splitImage(BufferedImage img, int cols, int rows)
          {
              int w = img.getWidth() / cols;
              int h = img.getHeight() / rows;
              int num = 0;
              
              BufferedImage imgs[] = new BufferedImage[w * h];
              
              for (int y = 0; y < rows; y++)
              {
                  for (int x = 0; x < cols; x++)
                  {
                      imgs[num] = new BufferedImage(w, h, img.getType());
                      
                      Graphics2D g = imgs[num].createGraphics();
                      g.drawImage(img, 0, 0, w, h, w * x, h * y, w * x + w, h * y + h, null);
                      g.dispose();
                      num++;
                  }
              }
              
              return imgs;
          }
          
          // image-loading method that will also alpha the color key for each tile
          public static BufferedImage makeColorTransparent(String ref, int color)
          {
              BufferedImage image = loadImage(ref);
              BufferedImage dimg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
              Graphics2D g = dimg.createGraphics();
              g.setComposite(AlphaComposite.Src);
              g.drawImage(image, null, 0, 0);
              g.dispose();
              
              for (int i = 0; i < dimg.getHeight(); i++)
              {
                  for (int j = 0; j < dimg.getWidth(); j++)
                  {
                      if (dimg.getRGB(j, i) == color)
                      {
                          dimg.setRGB(j, i, 0x8F1C1C);
                      }
                  }
              }
              
              return dimg;
          }
      }
      Lastly, here's the GameTest code:
      /* This class is what controls and runs the main game loop. */
      
      import javax.swing.JFrame;
      import javax.swing.*;
      import java.awt.*;
      
      public class GameTest
      {   
          public static void main(String args[])
          {
              // initialize the level, player, renderer, and display mode
              LevelRenderer myRenderer = new LevelRenderer();
              DisplayMode dm = new DisplayMode(1280, 768, 16, DisplayMode.REFRESH_RATE_UNKNOWN);
              
              myRenderer.run(dm);
          }
      }
        • 1. Re: My Attempt at Active Rendering is Very Slow?
          EJP
          You don't need to keep re-creating 'gr' every time around the loop, especially when you've already created it in the constructor, nor keep setting its background to black either.
          • 2. Re: My Attempt at Active Rendering is Very Slow?
            875749
            EJP,

            Thank you for the response. I adjusted for that in my code. However, it is still running at the same exact same speed. :/
            • 3. Re: My Attempt at Active Rendering is Very Slow?
              EJP
              Well there's lots of suboptimal code here, such as the getTile() method which doesn't even need to exist once you get your co-ordinate system right, and you don't need to check the same keycode for seven different values as you are: use a switch statement, but I guess my fundamental question is does the run() method really need to run continuously? or should it run at short intervals based on the movement quanta?
              • 4. Re: My Attempt at Active Rendering is Very Slow?
                875749
                EJP,

                Thank you again for your response. I optimized the processKey routines so that they used switch statements as you said, and I can't believe I hadn't thought of that before! However, I'm not sure exactly where to begin in regard to your pointer about the run method. Do you mean loop run() in main instead of calling it just once? I appreciate your help and advice very much.

                Colton
                • 5. Re: My Attempt at Active Rendering is Very Slow?
                  EJP
                  You have a run(DisplayMode) method that loops 'while (!endGame)' and never appears to sleep, unless something it calls does that. I haven't analysed all your code but it seems to me you're just moving players around according to keyboard input or maybe their current course and speed, and you don't need that to run flat chat I would have thought. You're just burning CPU cycles and not giving your other threads a chance to run.
                  • 6. Re: My Attempt at Active Rendering is Very Slow?
                    875749
                    EJP,

                    I actually used to have a sleep call in there previously and ended up taking it out as an experiment and never put it back in. I just did and now the updated class is posted below. However, it didn't appear to change the speed at all.

                    The code is actually moving the level around and redrawing the current view of the level based on a multi-dimensional array of tile values (0 or 1, 0 being black and 1 being a white design tile). The Player class just basically encapsulates the current animation of the player in the middle of the screen depending on where the user is moving and how to update this animation. In the end, it's just an illusion of movement, and from what I've learned and read on tile engines, this is how most side scrolling games work, so I chose this design. Eventually, I want this to be a class I can inherit from for different level types that use different tile images that will comprise the image, rather than just 2 tiles right now. It is my first side-scrolling engine, so there is of course much for me to learn and optimize, and the same goes for programming in general, something I probably will never completely master because of its expansive nature.

                    Anyways, here is the updated LevelRenderer class, and I appreciate all of your help. I really do hope there's something that can be done to make the renderer function much faster.
                    /* This class's job is to manage a Player and Level object and call their render and update routines. */
                     
                    import java.awt.*;
                    import java.awt.event.*;
                    import java.awt.image.*;
                    import java.io.*;
                    import javax.imageio.*;
                    import javax.swing.JFrame;
                    import javax.swing.*;
                    import java.util.Random;
                    import java.awt.Color;
                    
                    public class LevelRenderer extends JFrame
                    {   
                        //
                        // CONSTANTS
                        //
                        
                        private final int TILE_SIZE = 14;
                        private final int SCREEN_WIDTH = 1280;
                        private final int SCREEN_HEIGHT = 768;
                        
                        //
                        // END OF CONSTANTS
                        //
                        
                        // will be used as a buffer before everything is drawn to the screen
                        private BufferedImage buffer2;
                        
                        // back buffer
                        private BufferStrategy buffer;
                        
                        // character object
                        private Player myPlayer;
                        
                        // level object
                        private Level myLevel;
                        
                        // screen object
                        private Screen s;
                        
                        // graphics object of the buffer
                        private Graphics gr;
                        
                        // Graphics object for the buffer strategy
                        private Graphics graphics;
                        
                        // boolean to determine when to end the game
                        private boolean endGame;
                        
                        // CONSTRUCTOR
                        public LevelRenderer()
                        {
                            setPreferredSize(new Dimension(1280, 768));
                            setIgnoreRepaint( true );
                            setUndecorated( true );
                    
                            setFocusable(true);
                            requestFocus();
                            
                            setResizable(false);
                            
                            addKeyListener( new KeyAdapter() 
                            {
                                public void keyPressed(KeyEvent e)
                                { 
                                    processKey(e);  
                                }
                                
                                public void keyReleased(KeyEvent e)
                                {
                                    processRelease(e);
                                }
                            });
                            
                            buffer2 = new BufferedImage(1280, 768, BufferedImage.TYPE_INT_ARGB);
                            
                            buffer2.createGraphics();
                            gr = buffer2.getGraphics();
                            
                            myPlayer = new Player();
                            myLevel = new Level("obstaclemap");
                            
                            endGame = false;
                        }
                        
                        // method to simply load an image from a path
                        public static BufferedImage loadImage(String ref)
                        {
                            BufferedImage bimg = null;
                               
                            try
                            {
                               bimg = ImageIO.read(new File(ref));
                            }
                            catch (Exception e)
                            {
                                e.printStackTrace();
                            }
                           
                            return bimg;
                        }
                        
                        // Run method for class
                        public void run(DisplayMode dm)
                         {     
                            setBackground(Color.WHITE);
                              s = new Screen();
                            s.setFullScreen(dm, this);
                            
                            this.createBufferStrategy( 2 );
                            buffer = this.getBufferStrategy();
                    
                            while (!endGame)
                            {
                                try
                                {   
                                    // edit player and level
                                    myLevel.renderLevel();
                                    myPlayer.animatePlayer();
                                    myLevel.drawLevel(gr, 0, 0);
                                    myPlayer.drawPlayer(gr, (SCREEN_WIDTH / 2) - TILE_SIZE / 2, (SCREEN_HEIGHT / 2) - TILE_SIZE);
                                    
                                    graphics = buffer.getDrawGraphics();
                                    graphics.drawImage(buffer2, 0, 0, null);
                                    
                                    if( !buffer.contentsLost() )
                                    {
                                        buffer.show();
                                    }
                                }
                                catch (Exception ex) 
                                { 
                                    System.err.println("Game Update Error: " + ex);
                                }
                                
                                try
                                {
                                    Thread.sleep(10);
                                }
                                catch (Exception ex)
                                {
                                    System.out.println("Can't sleep!");
                                }
                            }
                            
                              s.restoreScreen();
                         } 
                        
                        // method to handle inputs and adjust the player accordingly
                        public void processKey(KeyEvent e)
                        {
                            int keyCode = e.getKeyCode();
                            boolean moved = false;
                            int xDisplace, yDisplace;
                            
                            // termination key
                            if (keyCode == KeyEvent.VK_ESCAPE)
                            {
                                endGame = true;
                            }
                            
                            // 0 - up
                            // 1 - left
                            // 2 - right
                            // 3 - down
                            // 4 - jump
                            
                            switch (keyCode)
                            {
                                case KeyEvent.VK_UP:
                                    myPlayer.updatePlayer(0);
                                    myLevel.updateLevel(0);
                                    break;
                                case KeyEvent.VK_LEFT:
                                    myPlayer.updatePlayer(1);
                                    myLevel.updateLevel(1);
                                    break;
                                case KeyEvent.VK_RIGHT:
                                    myPlayer.updatePlayer(2);
                                    myLevel.updateLevel(2);
                                    break;
                                case KeyEvent.VK_DOWN:
                                    myPlayer.updatePlayer(3);
                                    myLevel.updateLevel(3);
                                    break;
                                case KeyEvent.VK_SPACE:
                                    myPlayer.updatePlayer(4);
                                    myLevel.updateLevel(4);
                                    break;
                            }
                        }
                        
                        // method to handle inputs and adjust the player accordingly
                        public void processRelease(KeyEvent e)
                        {
                            int keyCode = e.getKeyCode();
                            boolean moved = false;
                            int xDisplace, yDisplace;
                            
                            // 0 - up
                            // 5 - left
                            // 6 - right
                            // 3 - down
                            // 4 - jump
                            
                            switch (keyCode)
                            {
                                case KeyEvent.VK_UP:
                                    myPlayer.updatePlayer(0);
                                    break;
                                case KeyEvent.VK_LEFT:
                                    myPlayer.updatePlayer(5);
                                    break;
                                case KeyEvent.VK_RIGHT:
                                    myPlayer.updatePlayer(6);
                                    break;
                                case KeyEvent.VK_DOWN:
                                    myPlayer.updatePlayer(3);
                                    break;
                                case KeyEvent.VK_SPACE:
                                    myPlayer.updatePlayer(4);
                                    break;
                            }
                        }
                    }
                    Colton
                    • 7. Re: My Attempt at Active Rendering is Very Slow?
                      EJP
                      graphics = buffer.getDrawGraphics();
                      Do you really need to do that every time around the loop?
                      • 8. Re: My Attempt at Active Rendering is Very Slow?
                        875749
                        EJP,

                        I tried incorporating that into run before the while loop to just call it once, but it ends up just displaying the very first render of the program and never updating after that.
                        • 9. Re: My Attempt at Active Rendering is Very Slow?
                          EJP
                          Does all this run standalone?
                          • 10. Re: My Attempt at Active Rendering is Very Slow?
                            875749
                            EJP,

                            I'm sorry, but what do you mean?
                            • 11. Re: My Attempt at Active Rendering is Very Slow?
                              EJP
                              I mean is there enough there for me to compile and execute?
                              • 12. Re: My Attempt at Active Rendering is Very Slow?
                                875749
                                EJP,

                                There isn't quite enough with the source code shown above for you to compile because it also requires a couple of image files. I'd be happy to put together a .zip with everything ready to compile and go, if that would be okay with you, sir? If so, would you prefer it sent to your bigpond email or elsewhere? Thank you very much.

                                Colton