Please Read - Im stumped
Been working on this game for about 2 months now, i work on it when i get free time between high school and sport etc etc.
Its a 2D Tiles based multiplayer shooter, everything works as it should at this stage, but my FPS is well below what i would like and probably require.
Previous to adding some lighting effects (ill explain later) my FPS was around 50 - 100, for some reason it switched every frame. That was aceptable, but not really great.
my rendering for the above looked like this:
for(int y = 0; y < screenHeight / tileHeight; y++){
for(int x = 0; x < screenWidth / tileWidth; x++){
if(map[y][x] == 0){
g.drawImage(tile, x * tileWidth, y * tileHeight,null);
}
if(map[y][x] == 2){
g.drawImage(tile, x * tileWidth, y * tileHeight,null);
}
if(map[y][x] == 3){
g.drawImage(tile, x * tileWidth, y * tileHeight,null);
}
}
}
Ok g was a graphics object pointing to BufferStrategy.getDrawGraphics();
So yea, im using bufferStrategy.
Now ive added a little effect of the player holding a flashLight which will come in use on dark maps. However to do pixel lighting i need to access the pixels, so i use bufferedImage and infortunately the only way ive found which willl work is this:
BufferedImage tileBuffer;
for(int y = 0; y < screenHeight / tileHeight; y++){
for(int x = 0; x < screenWidth / tileWidth; x++){
if(map[y][x] == 0){
gTile.drawImage(tile, 0, 0,null);
}
if(map[y][x] == 2){
gTile.drawImage(tile,0, 0,null);
}
if(map[y][x] == 3){
gTile.drawImage(tile, 0, 0,null);
}
//Do lighting by creating polygon (triangle) with the mouse co-ords and light neccery pixels if the tile intercepts the polygon.
g.drawImage(tileBuffer, x * 50, y * 50,null);
}
}
gTile is a graphics object pointing to tileBuffer.createGraphics();
I believe this was the reason for my FPS drop, before i only had to draw straight to he bufferStrat but now i hve to draw the tile to a buffferedImage and then the bufferStrat. I've tested and profiled my code and i believe im correct.
Before Lighting FPS: 50 - 100
After Lighting Implemented FPS: 20
Now im gona ask a huge favour, below im going to paste majority of my rendering code, i would be greatly appreciated if you could help me improve my FPS greatly.
I know its a big ask, but please just hve a quick look, it might be something so simple that im just not aware of atm.
Thanks in advance, Nick.
import javax.swing.*;
import java.awt.image.*;
import java.awt.*;
import java.util.*;
publicclass Map{
Rectangle rect;
Color[][] grassColors =new Color[50][50];
Color[][] rockColors =new Color[50][50];
Color[][] skyColors =new Color[50][50];
Color[][] waterColors =new Color[50][50];
int screenWidth = 800;
int screenHeight = 800;
int tileHeight = 50;
int tileWidth = 50;
Graphics2D g;
BufferedImage tile;
BufferedImage tileLight;
int lightPosX;
int lightPosY;
int pointerX;
int pointerY;
int height;
int width;
Color change;
long startTime;
long finnishTime;
double d1;//Distance from mouse to origin
double d2;//Distance from origin to measure point
double d3;//Distance from mouse to measure point
double measurePointX;
double measurePointY;
double angleDeg;
int[] xPoints =newint[3];
int[] yPoints =newint[3];
Polygon flashLight;
double angle = 0;
double angleDiff = .5;
int radius = 175;//Distance light travels
double p1X;
double p1Y;
double p2X;
double p2Y;
int mapX, mapY;
int playerx;
int playery;
WarPanel reference;
Iterator it;
ClientIO io;
//Map
int[][] map ={{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,4,2,2,2,4,2,2,2,2,2,4,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},};
//End Map
BufferedImage buffImage;
Image grass;
Image rock;
Image sky;
Image water;
BufferedImage renew;
BufferedImage grassBuffer;
BufferedImage rockBuffer;
BufferedImage skyBuffer;
BufferedImage waterBuffer;
public Map(WarPanel ref, ClientIO c){
io = c;
reference = ref;
renew =new BufferedImage(16 * 50, 16 * 50, BufferedImage.TYPE_INT_ARGB);
buffImage =new BufferedImage(16 * 50, 16 * 50, BufferedImage.TYPE_INT_ARGB);
grass =new ImageIcon("Grass.jpg").getImage();
rock =new ImageIcon("Rock.jpg").getImage();
sky =new ImageIcon("stars.jpg").getImage();
water =new ImageIcon("Water.jpg").getImage();
grassBuffer =new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB );
g = grassBuffer.createGraphics();
g.drawImage(grass, 0, 0,null);
rockBuffer =new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB );
g = rockBuffer.createGraphics();
g.drawImage(rock, 0, 0,null);
skyBuffer =new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB );
g = skyBuffer.createGraphics();
g.drawImage(sky, 0, 0,null);
waterBuffer =new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB );
g = waterBuffer.createGraphics();
g.drawImage(water, 0, 0,null);
//Set Up Lighting
tile =new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB );
g = tile.createGraphics();
getColors();
//Below Darken Tiles
/*
for(int y = 0; y < tile.getHeight(); y++){
for(int x = 0; x < tile.getWidth(); x++){
change = new Color(tile.getRGB(x, y)).darker();
tile.setRGB(x, y, change.getRGB());
}
}
*/
lightPosX = 400;
lightPosY = 400;
measurePointX = lightPosX + 5;
measurePointY = lightPosY;
rect =new Rectangle();
flashLight =new Polygon();
}
publicvoid drawMap(Graphics g2D,int p,int p1,int x,int y){
try{
int offsetX = x;
int offsetY = y;
//Begin Lighting Math
int pointerX = reference.crossHairX;
int pointerY = reference.crossHairY;
d1 = Math.sqrt((pointerX - lightPosX)*(pointerX - lightPosX) + (pointerY - lightPosY)*(pointerY - lightPosY));
d2 = Math.sqrt((measurePointX - lightPosX)*(measurePointX - lightPosX) + (measurePointY - lightPosY)*(measurePointY - lightPosY));
d3 = (pointerX - measurePointX)*(pointerX - measurePointX) + (pointerY - measurePointY)*(pointerY - measurePointY);
angle = -(Math.acos((d1*d1 + d2*d2 - d3)/(2*d1*d2)));
if(pointerY > lightPosY){
angle = 6.283185307 - angle;
}
//Rotating Triangle - This below code snipet was passed to me by kajbj.
angle = angle - .994837674;
p1X = Math.cos(angle) * radius - Math.sin(angle) * radius;
p1Y = Math.sin(angle) * radius + Math.cos(angle) * radius;
p2X = Math.cos(angle+angleDiff) * radius - Math.sin(angle+angleDiff) * radius;
p2Y = Math.sin(angle+angleDiff) * radius + Math.cos(angle+angleDiff) * radius;
//End snipet, thank you kajbj :)
xPoints[0] = lightPosX;
xPoints[1] = (int)p1X + lightPosX;
xPoints[2] = (int)p2X + lightPosX;
yPoints[0] = lightPosY;
yPoints[1] = (int)p1Y + lightPosY;
yPoints[2] = (int)p2Y + lightPosY;
flashLight.reset();
flashLight.addPoint(xPoints[0], yPoints[0]);
flashLight.addPoint(xPoints[1], yPoints[1]);
flashLight.addPoint(xPoints[2], yPoints[2]);
//End Lighting Math
for(int c = y / tileHeight; c <= 16 + ( y / tileHeight) + 1; c++){
for(int r = x / tileWidth; r <= 16 + ( x / tileWidth) + 1; r++){
int xDraw = r * tileWidth - offsetX;
int yDraw = c * tileHeight - offsetY;
if((c > 32)||(c < 0)||(r > 32)||(r < 0)){
//Do nothing
}
else{
if(map[c][r] == 0){
//g2D.drawImage(grass, 0, 0, (int)(50 - xDraw), 0, (int)(-1*xDraw), 0, L, 0, null);
g.drawImage(grassBuffer, 0, 0,null);
//tile = grassBuffer;
}
if(map[c][r] == 1){
g.drawImage(rockBuffer, 0, 0,null);
//tile = rockBuffer;
}
if(map[c][r] == 2){
g.drawImage(rockBuffer,0, 0,null);
//tile = rockBuffer;
}
if(map[c][r] == 4){
g.drawImage(waterBuffer, 0, 0,null);
//tile = waterBuffer;
}
rect.setRect(xDraw, yDraw, 50, 50);
if(flashLight.intersects(rect)){
int pChange = 0;
for(int y1 = 0; y1 < 50; y1 += 2){
int yDist = (y1 + yDraw - lightPosY)*(y1 + yDraw - lightPosY);
for(int x1 = 0; x1 < 50; x1 += 2){
if(flashLight.contains(x1 + xDraw,y1 + yDraw)){
double dSource = (x1 + xDraw - lightPosX)*(x1 + xDraw - lightPosX) + yDist;
change =new Color(tile.getRGB(x1, y1));
int even = pChange % 2;
if(dSource < 30625){
if(dSource > 25600){
if(even == 0){
change = change.brighter();
}
}
else{
change = change.brighter();
}
}
else{
change = change.brighter();
}
if(dSource < 2500){
if(dSource > 625){
if(even == 0){
change = change.brighter();
}
}
else{
change = change.brighter();
}
}
if(dSource < 10000){
if(dSource > 5625){
if(even == 0){
change = change.brighter();
}
}
else{
change = change.brighter();
}
}
if(dSource < 22500){
if(dSource > 15625){
if(even == 0){
change = change.brighter();
}
}
else{
change = change.brighter();
}
}
tile.setRGB(x1, y1, change.getRGB());
pChange += 1;
}//End If polygon contains
}//End For - X
pChange = 0;
}//End For - Y
}//End if intercepts
g2D.drawImage(tile, xDraw, yDraw, 50, 50,null);
//restoreColors(); Killed FPS: 1
}//End Else From First Loop
}//End r
}//End c
if((io.opX >= x) && (io.opY >= y)){
g2D.drawRect(io.opX - reference.imgCropx1, io.opY - reference.imgCropy1, 20, 20);
}
Bullet temp;
int v;
v = 0;
it = reference.bullets.iterator();
while(it.hasNext()){
temp = (Bullet)it.next();
if(((int)temp.bx >= x) && ((int)temp.by >= y)){
g2D.drawOval((int)temp.bx - reference.imgCropx1, (int)temp.by - reference.imgCropy1, 10, 10);
}
v++;
}
it = reference.opBullets.iterator();
while(it.hasNext()){
temp = (Bullet)it.next();
if(((int)temp.bx >= x) && ((int)temp.by >= y)){
g2D.drawOval((int)temp.bx - reference.imgCropx1, (int)temp.by - reference.imgCropy1, 10, 10);
}
v++;
}
}catch(Exception e){System.out.println(e +" Caught"); drawMap(g2D,p,p1, x, y);}
//return buffImage;
}
publicvoid getColors(){
g.drawImage(grass, 0, 0,null);
for(int y = 0; y < tile.getHeight(); y++){
for(int x = 0; x < tile.getWidth(); x++){
grassColors[y][x] =new Color(tile.getRGB(x, y));
}
}
g.drawImage(rock, 0, 0,null);
for(int y = 0; y < tile.getHeight(); y++){
for(int x = 0; x < tile.getWidth(); x++){
rockColors[y][x] =new Color(tile.getRGB(x, y));
}
}
g.drawImage(water, 0, 0,null);
for(int y = 0; y < tile.getHeight(); y++){
for(int x = 0; x < tile.getWidth(); x++){
waterColors[y][x] =new Color(tile.getRGB(x, y));
}
}
g.drawImage(sky, 0, 0,null);
for(int y = 0; y < tile.getHeight(); y++){
for(int x = 0; x < tile.getWidth(); x++){
skyColors[y][x] =new Color(tile.getRGB(x, y));
}
}
}
publicvoid restoreColors(){
for(int y = 0; y < 50; y++){
for(int x = 0; x < 50; x++){
grassBuffer.setRGB(x, y, grassColors[y][x].getRGB());
}
}
/*for(int y = 0; y < 50; y++){
for(int x = 0; x < 50; x++){
rockBuffer.setRGB(x, y, rockColors[y][x].getRGB());
}
}
for(int y = 0; y < 50; y++){
for(int x = 0; x < 50; x++){
waterBuffer.setRGB(x, y, waterColors[y][x].getRGB());
}
}
*/
}
}

