• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Noegddgeon

Java Tile Engine Super Slow

23 posts in this topic

Hey, guys! Been a while since I've posted anything.

I'm working on a side-scrolling game in Java. The issue at hand is that I've created the needed classes for scrolling and rendering the character and the level, only it is very slow. I'm not sure if this is a Java limitation or what, but I would be greatly appreciative if someone could perhaps tell me what it is either I'm doing wrong or what needs to be added to make the scrolling and rendering faster. I would think my machine (quad-core 3.4 GHz processor, 8 GB of ram, superpower graphics card, etc.) would run this program way faster and more efficiently, but I don't know if maybe there are things under the hood that I am missing. I'll post the classes that comprise the engine below.

Here's a general view of what I've made: I have a Player class, a Level class, and a LevelRenderer class. The Level loads a black and white pixel map that represents the level's tiles and converts it to an array, loads and holds the tile images to blit, stores the current coordinates of the camera view, and has a method to draw its current view. The Player class can draw the Player sprite always in the middle of the screen, and the LevelRenderer instantiates one of each of the Player and Level and handles input, being an extended JFrame. I have another class called GameTest that has a main method to create a LevelRenderer object, but that's probably irrelevant, as it only calls the run() method of the LevelRenderer and the constructor pretty much and lets the other classes do all the work. In the end, it's a simple scrolling engine that keeps the character in the middle of the screen at all times and just updates the level.

This is my first side-scrolling engine, so if you have any constructive criticism to offer, I would be greatly appreciative of that, as well. I mostly tried to piece together what information I could find about them and tried designing part of it myself. I've found it's not usually right the first time when I undertake something fairly complex like this, but it's certainly rewarding.

Thanks again for taking a look! And I apologize of the post gets a little bit lengthy :P

Here's the Level class:

[code]

/* 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;
}
}
[/code]

Here's the Player class:

[code]

/* 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;
}
}
}
[/code]

And here's the LevelRenderer class:

[code]

/* 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 buffer;

// character object
private Player myPlayer;

// level object
private Level myLevel;

// screen object
private Screen s;

// graphics object of the buffer
private Graphics gr;

// boolean to determine when to end the game
private boolean endGame;

// CONSTRUCTOR
public LevelRenderer()
{
setPreferredSize(new Dimension(1280, 768));

setFocusable(true);
requestFocus();

setResizable(false);

addKeyListener( new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
processKey(e);
}

public void keyReleased(KeyEvent e)
{
processRelease(e);
}
});

buffer = new BufferedImage(1280, 768, BufferedImage.TYPE_INT_ARGB);

buffer.createGraphics();
gr = buffer.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();

try
{
s.setFullScreen(dm, this);
}
catch (Exception ex)
{
System.out.println("Error creating rendered tiles!");
}

while (!endGame)
{
try
{
Thread.sleep(2);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}

try
{
myLevel.renderLevel();
myLevel.drawLevel(gr, 0, 0);

myPlayer.animatePlayer();
myPlayer.drawPlayer(gr, (SCREEN_WIDTH / 2) - TILE_SIZE / 2, (SCREEN_HEIGHT / 2) - TILE_SIZE);
}
catch (NullPointerException ex)
{
System.err.println("Game Update Error: " + ex);
}

try
{
repaint();
}
catch (Exception ex)
{
System.err.println("Repaint Error: " + ex);
}
}

s.restoreScreen();
}

// method to draw the tiles on the screen
public void paint(Graphics g)
{
g.drawImage(buffer, 0, 0, null);
}

// 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;
}

// 1 - up
// 2 - left
// 3 - right
// 4 - down
// 5 - jump

if (keyCode == KeyEvent.VK_UP)
{
try
{
myPlayer.updatePlayer(0);
myLevel.updateLevel(0);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_LEFT)
{
try
{
myPlayer.updatePlayer(1);
myLevel.updateLevel(1);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_RIGHT)
{
try
{
myPlayer.updatePlayer(2);
myLevel.updateLevel(2);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_DOWN)
{
try
{
myPlayer.updatePlayer(3);
myLevel.updateLevel(3);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_SPACE)
{
try
{
myPlayer.updatePlayer(4);
myLevel.updateLevel(4);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
}

// method to handle inputs and adjust the player accordingly
public void processRelease(KeyEvent e)
{
int keyCode = e.getKeyCode();
boolean moved = false;
int xDisplace, yDisplace;

// 1 - up
// 2 - left
// 3 - right
// 4 - down
// 5 - jump

if (keyCode == KeyEvent.VK_UP)
{
try
{
myPlayer.updatePlayer(0);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_LEFT)
{
try
{
myPlayer.updatePlayer(5);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_RIGHT)
{
try
{
myPlayer.updatePlayer(6);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_DOWN)
{
try
{
myPlayer.updatePlayer(3);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_SPACE)
{
try
{
myPlayer.updatePlayer(4);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
}
}
[/code]

If anything else is needed, please let me know and I will gladly post or elaborate. The LevelCollisions class is irrelevant at this point, as I haven't implemented the functions that will make it work. Eventually, it will be what determines whether the player can move or not. Right now, you can pretty much move the character in any direction and the level will scroll, regardless of terrain.
0

Share this post


Link to post
Share on other sites
Read this: [url="http://www.gamedev.net/page/resources/_/technical/general-programming/java-games-active-rendering-r2418"]http://www.gamedev.net/page/resources/_/technical/general-programming/java-games-active-rendering-r2418[/url]
0

Share this post


Link to post
Share on other sites
[quote name='VildNinja' timestamp='1317713147' post='4868877']
Read this: [url="http://www.gamedev.net/page/resources/_/technical/general-programming/java-games-active-rendering-r2418"]http://www.gamedev.n...rendering-r2418[/url]
[/quote]

*face palm*

Thank you so much. I'll get right to work. :]
0

Share this post


Link to post
Share on other sites
Okay, so I read that article and rewrote the LevelRenderer so that it uses active rendering instead of passive rendering. When it outputs to the screen, however, all I see is white. What would be causing this? Thank you so much for your help, and here is the updated LevelRenderer code:

[code]

/* 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();

try
{
s.setFullScreen(dm, this);
}
catch (Exception ex)
{
System.out.println("Error setting full screen");
}

try
{
this.createBufferStrategy( 2 );
buffer = this.getBufferStrategy();
}
catch (Exception ex)
{
System.out.println("Error creating buffer strategy!");
}

while (!endGame)
{
try
{
// clear back buffer...
gr = buffer2.createGraphics();
gr.setColor(Color.BLACK);

// edit player and level
myLevel.renderLevel();
myPlayer.animatePlayer();
myPlayer.drawPlayer(gr, (SCREEN_WIDTH / 2) - TILE_SIZE / 2, (SCREEN_HEIGHT / 2) - TILE_SIZE);
myLevel.drawLevel(gr, 0, 0);

graphics = buffer.getDrawGraphics();
graphics.drawImage(buffer2, 0, 0, null);
}
catch (NullPointerException 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;
}

// 1 - up
// 2 - left
// 3 - right
// 4 - down
// 5 - jump

if (keyCode == KeyEvent.VK_UP)
{
try
{
myPlayer.updatePlayer(0);
myLevel.updateLevel(0);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_LEFT)
{
try
{
myPlayer.updatePlayer(1);
myLevel.updateLevel(1);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_RIGHT)
{
try
{
myPlayer.updatePlayer(2);
myLevel.updateLevel(2);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_DOWN)
{
try
{
myPlayer.updatePlayer(3);
myLevel.updateLevel(3);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_SPACE)
{
try
{
myPlayer.updatePlayer(4);
myLevel.updateLevel(4);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
}

// method to handle inputs and adjust the player accordingly
public void processRelease(KeyEvent e)
{
int keyCode = e.getKeyCode();
boolean moved = false;
int xDisplace, yDisplace;

// 1 - up
// 2 - left
// 3 - right
// 4 - down
// 5 - jump

if (keyCode == KeyEvent.VK_UP)
{
try
{
myPlayer.updatePlayer(0);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_LEFT)
{
try
{
myPlayer.updatePlayer(5);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_RIGHT)
{
try
{
myPlayer.updatePlayer(6);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_DOWN)
{
try
{
myPlayer.updatePlayer(3);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_SPACE)
{
try
{
myPlayer.updatePlayer(4);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
}
}
[/code]
0

Share this post


Link to post
Well, I rewrote the LevelRenderer class so that it uses passive instead of active rendering. However, it is still scrolling at the same speed it was when I implemented it passively. Did I perhaps do something wrong trying to convert the code? The example used all of the code in main, as opposed to in my class, I use run() to hold all of the game's update code. Perhaps this is the culprit? I'll show the code below of my class. Thank you so much for the help!

[code]


/* 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();

try
{
s.setFullScreen(dm, this);
}
catch (Exception ex)
{
System.out.println("Error setting full screen");
}

try
{
this.createBufferStrategy( 2 );
buffer = this.getBufferStrategy();
}
catch (Exception ex)
{
System.out.println("Error creating buffer strategy!");
}

while (!endGame)
{
try
{
// clear back buffer...
gr = buffer2.createGraphics();
gr.setColor(Color.BLACK);

// edit player and level
myLevel.renderLevel();
myPlayer.animatePlayer();
myPlayer.drawPlayer(gr, (SCREEN_WIDTH / 2) - TILE_SIZE / 2, (SCREEN_HEIGHT / 2) - TILE_SIZE);
myLevel.drawLevel(gr, 0, 0);

graphics = buffer.getDrawGraphics();
graphics.drawImage(buffer2, 0, 0, null);

if( !buffer.contentsLost() )
{
buffer.show();
}
}
catch (NullPointerException 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;
}

// 1 - up
// 2 - left
// 3 - right
// 4 - down
// 5 - jump

if (keyCode == KeyEvent.VK_UP)
{
try
{
myPlayer.updatePlayer(0);
myLevel.updateLevel(0);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_LEFT)
{
try
{
myPlayer.updatePlayer(1);
myLevel.updateLevel(1);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_RIGHT)
{
try
{
myPlayer.updatePlayer(2);
myLevel.updateLevel(2);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_DOWN)
{
try
{
myPlayer.updatePlayer(3);
myLevel.updateLevel(3);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_SPACE)
{
try
{
myPlayer.updatePlayer(4);
myLevel.updateLevel(4);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
}

// method to handle inputs and adjust the player accordingly
public void processRelease(KeyEvent e)
{
int keyCode = e.getKeyCode();
boolean moved = false;
int xDisplace, yDisplace;

// 1 - up
// 2 - left
// 3 - right
// 4 - down
// 5 - jump

if (keyCode == KeyEvent.VK_UP)
{
try
{
myPlayer.updatePlayer(0);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_LEFT)
{
try
{
myPlayer.updatePlayer(5);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_RIGHT)
{
try
{
myPlayer.updatePlayer(6);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_DOWN)
{
try
{
myPlayer.updatePlayer(3);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
if (keyCode == KeyEvent.VK_SPACE)
{
try
{
myPlayer.updatePlayer(4);
}
catch (Exception ex)
{
System.err.println("Error: " + ex);
}
}
}
}
[/code]

Colton
0

Share this post


Link to post
Share on other sites
You are skipping the entire canvas and graphics environment part of the article. Besides that, you are using an enormous amount of try catch blocks. Instead of checking for null pointer exceptions you should just check for null, before using whatever you fear to be null.

Hope this helps
0

Share this post


Link to post
Share on other sites
[quote name='VildNinja' timestamp='1317726844' post='4868941']
You are skipping the entire canvas and graphics environment part of the article. Besides that, you are using an enormous amount of try catch blocks. Instead of checking for null pointer exceptions you should just check for null, before using whatever you fear to be null.

Hope this helps
[/quote]

I see your point with the try-catch blocks. I've edited them out properly and it looks much better as a result, too. Regarding the canvas, however, I'm using a full-screen app, and the Canvas was only used in a windowed app. Also, I've already been using a class that manages a GraphicsEnvironment, which I will show below. The application is still running at the same slow rate.

The Screen class, which manages full-screen mode and the GraphicsEnvironment:

[code]

import java.awt.*;
import javax.swing.JFrame;

public class Screen
{
private GraphicsDevice vc;

public Screen()
{
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
vc = env.getDefaultScreenDevice();
}

public void setFullScreen(DisplayMode dm, JFrame window)
{
window.setUndecorated(true);
window.setResizable(false);
vc.setFullScreenWindow(window);

if (dm != null && vc.isDisplayChangeSupported())
{
try
{
vc.setDisplayMode(dm);
} catch (Exception ex) { }
}
}

public Window getFullScreenWindow()
{
return vc.getFullScreenWindow();
}

public void restoreScreen()
{
Window w = vc.getFullScreenWindow();
if (w != null)
{
w.dispose();
}

vc.setFullScreenWindow(null);
}
}
[/code]

The updated LevelRenderer class:

[code]

/* 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();
myPlayer.drawPlayer(gr, (SCREEN_WIDTH / 2) - TILE_SIZE / 2, (SCREEN_HEIGHT / 2) - TILE_SIZE);
myLevel.drawLevel(gr, 0, 0);

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);
}
}
}
[/code]

I appreciate all the help and your time, VildNinja!

Colton
0

Share this post


Link to post
Share on other sites
[quote name='VildNinja' timestamp='1317726844' post='4868941']
Besides that, you are using an enormous amount of try catch blocks. Instead of checking for null pointer exceptions you should just check for null, before using whatever you fear to be null.
[/quote]

Better yet, try to write the code in such a way that things [b]can't[/b] be null (or at least, such that the presence of a null is certainly a bug).
0

Share this post


Link to post
Share on other sites
It's your renderLevel() method.

Every time you draw your game, you redraw the entire tile map. Instead you should cache the tiles you've already drawn, so you wont have to draw them twice. The most common approach to this problem, is to have nine images setup like a tic-tac-toe board, so that the central image is containing the center of your camera. Whenever the camera moves, so the center enters another image you should discard the three images furthest away, and draw the three new images.

Hope this makes sense. I can't seem to find any good articles on the topic, but it's a very common approach.
0

Share this post


Link to post
Share on other sites
Okay, thank you very much for the advice. I've been doing a lot of work on the program in the last couple days, and I have more to do, but I'll try and incorporate the tic-tac-toe image structure to hopefully fix things. Once I do and have something working, I'll post as an example for the sake of the forum and also to see if it's done properly. :] Appreciate the help!

Colton

0

Share this post


Link to post
Share on other sites
Here is what I would do.

Have a number of quads on the screen the size of a tile and textured with the tile textures to represent the world.
Moving the quads around is cake.
When new stuff is about to come into view make new quads, and apply the appropriate textures.
When stuff goes off screen you can just get rid of those quads.

The player and other objects can be handled the same way as long as zbuffering is off.

This way you don't have to manually blit textures to the screen every frame which seems to be killing you performance for some reason.
This should run at a billion frames per second on shit hardware.

Tell me if you don't understand I'm psleepy so...

EDIT:
For optimal performance, draw all quads that have the same texture in one go, then switch textures and draw a new batch.

EDIT2:
If this is kinds above your lvl thats cool, I dunno much about java or whatever the "Graphics" class is but if it's hardware accelerated it should be slamming even with your code.
0

Share this post


Link to post
Share on other sites
James,

That's probably something I'll try as well. What you're talking about sounds like OpenGL... the Graphics object is part of Java's stock library, from a part called the AWT (Abstract Windowing Toolkit). From what I seem to understand, it's not hardware accelerated, or else it wouldn't be so slow even with the code that's taking place right now, but I could very easily be wrong. (I probably am.)

That aside, I do see what you are saying and I've decided actually before even reading this post after doing more research that it would make sense to get familiar with 2D OpenGL programming and use it in conjunction with LWJGL. I've been wanting to harness the power of OpenGL for quite some time, and now I finally have an excuse to get cracking. And I can directly apply your quad technique once I do so, having already learned a little bit about it in the time I've spent setting up LWJGL. It seems to be wise, as well as a much more powerful alternative than AWT and Swing.

I appreciate the help!


Colton
0

Share this post


Link to post
Share on other sites
You prolly dont even need a wrapper for open gl honestly, it's a pretty small.
It almost seems like it would take the same amount of time to learn to use a wrapper than the use the api itself.
But either way is great.

EDIT:
But I'm not even sure how using the api itself would work out on java so maybe you need a wrapper I'm not sure.

glhf!
0

Share this post


Link to post
Share on other sites
[quote name='Noegddgeon' timestamp='1317985772' post='4870064']
That aside, I do see what you are saying and I've decided actually before even reading this post after doing more research that it would make sense to get familiar with 2D OpenGL programming and use it in conjunction with LWJGL. I've been wanting to harness the power of OpenGL for quite some time, and now I finally have an excuse to get cracking. And I can directly apply your quad technique once I do so, having already learned a little bit about it in the time I've spent setting up LWJGL. It seems to be wise, as well as a much more powerful alternative than AWT and Swing.
[/quote]
I do not know what you were doing wrong, but it's definitetly not AWT/Swing to blame. My tile based scroller gets ridiculous high frame rates while being based on pure drawImage() calls of Graphics objects, with a HUD on top as well.
0

Share this post


Link to post
Share on other sites
[quote name='6510' timestamp='1317989484' post='4870091']
I do not know what you were doing wrong, but it's definitetly not AWT/Swing to blame. My tile based scroller gets ridiculous high frame rates while being based on pure drawImage() calls of Graphics objects, with a HUD on top as well.
[/quote]

Hmm, I would say time the drawing and track the issue down but it will resolve itself when he switches to opengl.
Still interesting to know.
0

Share this post


Link to post
Share on other sites
James,


Java has a couple of interfacing libraries for OpenGL, JOGL and LWJGL being the two most popular from what I've seen. You need something of the sort to act as a wrapper for it, but they are very thin wrappers, and you have to know OpenGL to use them anyways, so I'll be learning OpenGL either way.

6510,

Do you mind elaborating a little bit more on your approach to the engine? I'm curious to see how we differed in our constructions.

Colton

0

Share this post


Link to post
Share on other sites
[quote name='Noegddgeon' timestamp='1318031689' post='4870314']
6510,

Do you mind elaborating a little bit more on your approach to the engine? I'm curious to see how we differed in our constructions.
[/quote]
Sure, but a bit diffcult because my stuff is spreaded over various framework and concrete game classes.
You already posted a few of your classes. Do you have a simple ready-to-debug Eclipse project at hand ? I could take a look if I dont have to set it up by myself.
Btw what is "slow" ?
One thing that could be a problem would be incompatible color models, but just a blind guess.
0

Share this post


Link to post
Share on other sites
6510,

I have a package in a zip archive with all of the classes and images that comprise the tile engine so far, but unfortunately I haven't been using Eclipse, just the command line. Recently, I've made the switch to Netbeans since I've begun to use LWJGL. Would you still be willing to take a look if I place here the zip archive with the classes? I imagine it would be fairly easy to import into an Eclipse project, but I understand if you don't want to take the time to do so. Thank you very much for your time!

Colton

0

Share this post


Link to post
Share on other sites
Okay, I took a quick look at it. The main differences to my approach are:

1. tile size
Your screen is 1280x768 with a tile size of 14 pixel, giving you more than 4900 calls of drawImage() for each and every frame
I am using 1024x768 with tiles of 64 pixel, resulting in only 192 calls.

2. tile rendering
You render the whole map each time.
I have an additional side column and row operating as scroll buffer. That means I dont have do redraw the whole map unless the player moves more than the tile size of 64 pixel. Before that you just take a different view window of the tile back buffer and draw it to the visible buffer in one call. Oh well, I am pretty bad in explaining...
0

Share this post


Link to post
Share on other sites
[quote name='6510' timestamp='1318149877' post='4870711']
Okay, I took a quick look at it. The main differences to my approach are:

1. tile size
Your screen is 1280x768 with a tile size of 14 pixel, giving you more than 4900 calls of drawImage() for each and every frame
I am using 1024x768 with tiles of 64 pixel, resulting in only 192 calls.

2. tile rendering
You render the whole map each time.
I have an additional side column and row operating as scroll buffer. That means I dont have do redraw the whole map unless the player moves more than the tile size of 64 pixel. Before that you just take a different view window of the tile back buffer and draw it to the visible buffer in one call. Oh well, I am pretty bad in explaining...
[/quote]

Actually, that makes a lot of sense... I'm going to have to recreate this section of the renderer and maybe redesign the entire approach to it and use something like 32 pixels for the tile size... for my game engine, 64 would be a little too big in order to capture what I want for the game, but 32 would make sense. It was looking too small for me anyway. But now I have a clearer view on how to implement the thing thanks to you... I appreciate the help very much! I'll post it here once it's been redesigned for future viewers to see, and hopefully it will work better as a result.

Best regards,
Colton
0

Share this post


Link to post
Share on other sites
Okay, I only changed a couple of the methods in Level to reflect what I had needed, as well as part of LevelRenderer.java, and the performance increase that should have grown tremendously is only hardly noticeable. Here are the differences I made:

Within Level.java:

[code]

// 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 + offsetX, y + offsetY, 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 = 0; y < SCREEN_HEIGHT; y += TILE_SIZE)
{
tileX = coordX;
for (x = 0; x < SCREEN_WIDTH; 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--;
this.renderLevel();
}
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--;
this.renderLevel();
}
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++;
this.renderLevel();
}
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++;
this.renderLevel();
}
break;
// jump
case 4:
break;
}
}
[/code]

And within LevelRenderer.java:

[code]

// 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
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();
}
[/code]

I made sure the code only calls to redraw the map once the user moves past a given offset of the screen where new tiles must be rendered and that it will simply shift the current image drawn of the map until that happens, as opposed to redrawing the entire view every loop. Did I implement this properly, or am I missing something? Your help is greatly appreciated! Btw, I haven't accounted yet for the increased tile sizes, but even still, shouldn't this be significantly faster? Thanks again.

Best regards,
Colton
0

Share this post


Link to post
Share on other sites
Just had to comment that this thread helped fix MY stupid little code problem which was making me crazy. thanx!


Anyway, I ran across an article describing a speed issue in Java itself which may or may not be applicable
to the original poster or may no longer exist in java7 but here's the link anyway:

[url="http://www.jhlabs.com/ip/managed_images.html"]http://www.jhlabs.co...ged_images.html[/url]

It describes how certain methods can confuse Java's handling of hardware acceleration:
-Raster.getDataBuffer()
-BufferedImage.getRGB()/setRGB()
-BufferedImage.getSubImage()
-Attaching an ImageObserver to a BufferedImage
-Filtering a BufferedImage with FilteredImageSource

Man, seems like the more i learn the less i know!
0

Share this post


Link to post
Share on other sites
Have you profiled your code? ([url="http://www.yourkit.com/"]http://www.yourkit.com/[/url] for example)

By the way, the following change halved the frame time on my computer (after taking into account the 10ms sleep delay)


In Level.java
[code]
// create blank camera canvas
cameraImage = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()0].getDefaultConfiguration().createCompatibleImage(SCREEN_WIDTH, SCREEN_HEIGHT);
//cameraImage = new BufferedImage(1280, 768, BufferedImage.TYPE_INT_ARGB);
//cameraImage.createGraphics();
cameraG = cameraImage.getGraphics();[/code]

The above creates temporary surfaces that don't require conversion when copying to a destination buffer.

Also, look into [font="Arial"]V[/font][color="#333333"][font="Arial"]olatileImage[/font][font="monospace"].[/font][/color]
0

Share this post


Link to post
Share on other sites
Colton, I've only skimmed most of the replies and the code since I'm at work but I haven't seen anyone suggesting turning on Java2D hardware acceleration yet. Have you tried that? AFAIK it's off by default. See [url="http://www.mymegabyte.com/2011/03/enable-opengl-hardware-acceleration-for-java-2d/"]here[/url] for how to enable it.
0

Share this post


Link to post
Share on other sites
its super slow because you using GUI system as your render >_<...
just use a graphic API like OpenGL to render your game.
my 3d java game (using LWJGL) renders me over 4,000 fps.

for more info:

[url="http://en.wikipedia.org/wiki/OpenGL"]http://en.wikipedia.org/wiki/OpenGL[/url]
[url="http://lwjgl.org/"]http://lwjgl.org/[/url]

hope its help you...
-1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0