Array Index Out Of Bounds When Drawing Pixels - java

I'm currently trying to draw pixels to my window and I seem to come across and index out of bounds error when the program starts. I honestly have no idea how to fix it. Can anybody tell me where the problem is? I've checked plenty of times but it seems like it should be just fine to me. I've given all the code for my project below, but the error is on the line in the render method (Game class) where the for loop is.
EDIT:
The error is somewhere in the for loop in the Game class. it says
java.lang.ArrayIndexOutOfBoundsException: 48601" at the line
"pixles[i] = screen.pixels[i]"
Screen Class
public class Screen {
private int width,height;
public int[] pixels;
public Screen(int width,int height){
this.width = width;
this.height = height;
pixels = new int[width * height];
}
public void render(){
for (int y = 0; y < height; y++){
for (int x = 0; x < width; x++){
pixels[x + y * width] = 0xff00ff;
}
}
}
}
Game Class
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
public class Game extends Canvas implements Runnable{
private int width = 300;
private int height = width / 16 * 9;
private int scale = 3;
private Thread thread;
private boolean running = false;
private JFrame frame;
private BufferedImage image = new BufferedImage(width * scale, height * scale,BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
private Screen screen;
public Game(){
screen = new Screen(width,height);
frame = new JFrame("Relm Of The Mad God Clone");
this.setPreferredSize(new Dimension(width * scale, height * scale));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(this);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
start();
}
public synchronized void start(){
thread = new Thread(this,"Running Thread");
thread.start();
running = true;
}
public synchronized void stop(){
try{
thread.join();
running = false;
}catch (InterruptedException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
Game g = new Game();
}
private void update(){
}
private void render(){
BufferStrategy buffer = getBufferStrategy();
if (buffer == null){
createBufferStrategy(3);
return;
}
screen.render();
for (int i = 0; i < pixels.length; i++){
pixels[i] = screen.pixels[i];
}
Graphics g = buffer.getDrawGraphics();
g.drawImage(image, 0, 0, getWidth(), getHeight(),this);
g.dispose();
buffer.show();
}
#Override
public void run() {
while (running){
update();
render();
}
}
}

The screen variable is initialized with new Screen(width, height), so it probably has width*height pixels. On the other hand, the pixels variable is initialized from image, which has width*scale * height*scale pixels.
Since scale=3, this means that the pixels array is 3 times longer than the screen array. That is why you are getting the exception.

Related

Java 3D Engine Pixel Drawing Problems

my 3 programs seem to work alone but when I try to run them together It seems to give me an out of bounds error but I cant tell where exactly if anyone can tell me where exactly it is and how to fix the error that would be great, I wanted to use a debugger but im having some problems getting it to work.
Here is my Code for the 3 Classes :
Render.java
package com.mime.Game.graphics;
public class Render {
public final int width;
public final int height;
public final int[] pixels;
public Render(int width, int height) {
this.width = width;
this.height = height;
pixels = new int[width * height];
}
public void draw(Render render, int xOffset, int yOffset) {
for(int x = 0; x < this.height; x++) {
int yPix = x + yOffset;
for(int y = 0; y < this.width; y++) {
int xPix = y + xOffset;
pixels[xPix + yPix * width] = render.pixels[x + y *
render.width];
}
}
}
}
Display.java
package com.mime.Game;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import com.mime.Game.graphics.Render;
import com.mime.Game.graphics.Screen;
import java.awt.image.DataBufferInt;
public class Display extends Canvas implements Runnable{
public static final long serialVersionUID = 1L;
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
private Thread thread;
private Screen screen;
private BufferedImage img;
private boolean running = false;
private Render render;
private int[] pixels;
public Display() {
screen = new Screen(WIDTH, HEIGHT);
img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
}
private void start() {
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
System.out.println("Working");
}
public void stop() {
if(!running)
return;
running = false;
try{
thread.join();
}catch(Exception e) {
e.printStackTrace();
System.exit(0);
}
}
public void run() {
while(running) {
tick();
render();
}
}
private void tick() {
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null) {
createBufferStrategy(3);
return;
}
screen.render();
for(int i = 0; i < WIDTH * HEIGHT; i++) {
pixels[i] = screen.pixels[i];
}
Graphics g = bs.getDrawGraphics();
g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
g.dispose();
bs.show();
}
public static void main(String[] args) {
Display game = new Display();
JFrame frame = new JFrame();
frame.setResizable(false);
frame.setSize(WIDTH, HEIGHT);
frame.add(game);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Chronicles of Walshy Alpha 0.01");
game.start();
}
}
screen.java :
package com.mime.Game.graphics;
import java.util.Random;
public class Screen extends Render{
private Render test;
public Screen(int width, int height) {
super(width, height);
Random random = new Random();
test = new Render(256, 256);
for(int i = 0; i < 256*256; i++) {
test.pixels[i] = random.nextInt();
}
}
public void render() {
draw(test, 0, 0);
}
}
In your Render.draw method you copy pixels from another Render object and you use this.width and this.height to access those pixels. This will fail when the other Render object's pixel size is smaller, which is the case in your code. You get an ArrayOutOfBoundsException when reading from render.pixels[x + y * render.width] because you're trying to read pixels from a 256*256 array as if it was a 800*600 array.
Additionally if you ever call draw with offset values, you will get another ArrayOutOfBoundsException, because you're simply adding the offsets to your x and y values without checking if the resulting index is too big when writing to pixels[xPix + yPix * width].
To fix this, you have to skip any value that goes beyond the width or height of either pixels array:
if (xPix > this.width || yPix > this.height || x > render.width || y > render.height)
{
continue;
}

Why is my BufferStrategy throwing a NullpointerException and how do I fix it? [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
I've been trying to make a 3d game and for some reason my code is throwing a NullPointerException. The error I'm getting is:
Exception in thread "Thread-3"
java.lang.NullPointerException
at Display_3d.render(Display_3d.java:73)
at Display_3d.run(Display_3d.java:55)
at java.lang.Thread.run(Unknown Source)
This program is supposed to just display pixels of a random color as a test in order to make 3d graphics later. There are two other classes it uses and even though those two don't throw errors they still could be the issue so I'll post them as well. The class Below is the one that throws the errors
import java.awt.Canvas;
import javax.swing.JFrame;
import java.awt.image.BufferedImage;
import java.awt.image.BufferStrategy;
import java.awt.image.DataBufferInt;
import java.awt.Graphics;
public class Display_3d extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
public static final int width = 800;
public static final int height = 600;
public static final String title = "Scott's Game Pre-Alpha 0.01";
private Thread thread;
private Screen screen;
private BufferedImage img;
private boolean running = false;
private Render render;
private int[] pixels;
public Display_3d(){
Screen screen = new Screen(width,height);
img = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
}
private void start(){
if (running){
return;
}
running = true;
Thread thread = new Thread(this);
thread.start();
System.out.println("start() has been called sucessfully");
}
private void stop(){
if (true != running){
return;
}
running = false;
try {
thread.join();
}catch (Exception e){
e.printStackTrace();
System.exit(0);
}
}
public void run(){
while (running){
tick();
/*Line 55*/render();
}
}
private void tick(){
}
private void render(){
BufferStrategy bs = this.getBufferStrategy();
if (bs == null){
this.createBufferStrategy(3);
return;
}
/*Line 73*/ screen.render();
for (int i = 0; i<width*height-1; i++){
pixels[i] = screen.pixels[i];
}
Graphics g = bs.getDrawGraphics();
g.drawImage(img,0,0,width,height,null);
g.dispose();
bs.show();
}
public static void main(String[] args){
Display_3d game = new Display_3d();
JFrame frame = new JFrame();
frame.add(game);
frame.pack();
frame.setTitle(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width,height);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
System.out.println("Running...");
game.start();
}
}
My Render Class
public class Render{
public final int width;
public final int height;
public final int[] pixels;
public Render (int width, int height){
this.width = width;
this.height = height;
pixels = new int[width * height];
}
public void draw(Render render, int xOffset, int yOffset){
for (int y = 0; y<render.height; y++){
int yPix = y + yOffset;
for (int x = 0; x<render.width; x++){
int xPix = x + xOffset;
pixels[xPix + yPix * width] = render.pixels[x+y * render.width];
}
}
}
public static void main (String[] args){}
}
My Screen Class
import java.util.Random;
public class Screen extends Render{
private Render test;
public Screen(int width, int height){
super(width,height);
Random random = new Random();
test = new Render(256,256);
for (int i = 0; i <256*256; i++){
test.pixels[i] = random.nextInt();
}
}
public void render() {
draw(test,0,0);
}
public static void main (String[] args){}
}
In you coonstructor you create local variable
public Display_3d(){
Screen screen = new Screen(width,height); //<-------------
img = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
}
Instead assign to the field
public Display_3d(){
this.screen = new Screen(width,height); //<-------------
img = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
}
The following:
if (bs == null){
this.createBufferStrategy(3);
will create a "buffer strategy", but it will not affect the value of bs, which has just been proven to be null. Therefore, your attempt to use bs further down is guaranteed to fail.

How do I solve this array out of bounds exception? [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 6 years ago.
Hello fellow hydrogen based life form. I learning how to make 3-Dimensional gaems from a top secret website (www.youtube.com) and I was learning from a very nice Youtuber. My project looks like this:
There are 3 classes: Main, Screen and Render
I get this exception :( :
Exception in thread "Thread-2" java.lang.ArrayIndexOutOfBoundsException: 65600
at Render.Draw(Render.java:20)
at Screen.render(Screen.java:19)
at Main.render(Main.java:74)
at Main.run(Main.java:59)
at java.lang.Thread.run(Unknown Source)
I shall upload my code here too below this. Please help me become good at this.
Main class:
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
public class Main extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
public static final String TITLE = "Nexus Overload";
private Thread t;
private boolean Running = false;
#SuppressWarnings("unused")
private Render ren;
private Screen s;
private BufferedImage img;
private BufferStrategy bs;
private int[] pixels;
public Main() {
s = new Screen(WIDTH, HEIGHT);
img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
}
private void start() {
if (Running)
return;
Running = true;
t = new Thread(this);
t.start();
}
#SuppressWarnings("unused")
private void stop() {
if (!Running)
return;
Running = false;
try {
t.join();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
public void run() {
while (Running) {
tick();
render();
}
}
private void tick() {
}
private void render() {
bs = this.getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
s.render();
for (int i = 0; i < WIDTH * HEIGHT; i++) {
pixels[i] = s.pixels[i];
}
Graphics g = bs.getDrawGraphics();
g.drawImage(img, WIDTH, HEIGHT, null);
g.dispose();
bs.show();
}
public static void main(String[] args) {
Main m = new Main();
JFrame frame = new JFrame();
frame.getContentPane().add(m);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(350, 100, WIDTH, HEIGHT);
frame.setTitle(TITLE);
frame.setVisible(true);
m.start();
}
}
Render class:
public class Render {
public final int width;
public final int height;
public final int[] pixels;
public Render(int width, int height) {
this.width = width;
this.height = height;
this.pixels = new int[width * height];
}
public void Draw (Render ren, int xOffset, int yOffset) {
for (int y = 0; y < ren.height; y++) {
int yPix = y + yOffset;
for (int x = 0; x < ren.width; x++) {
int xPix = x + xOffset;
pixels[xPix + yPix * width] = ren.pixels[xPix + yPix * width];
}
}
}
}
Screen class:
import java.util.Random;
public class Screen extends Render{
private Render ren;
public Screen(int width, int height) {
super(width, height);
Random r = new Random();
ren = new Render(256, 256);
for (int i = 0; i < 256 * 256; i++) {
ren.pixels[i] = r.nextInt();
}
}
public void render() {
Draw(ren, 0, 0);
}
}
For those who want image with eclipse debugging, here:
With variables tab selected:
Your exception is pointing us to the Draw method in the Render class (NB: Java conventions state that method names should be lower case so this method should actually be called draw(Render ren, int xOffset, int yOffset). I would first try and set the int y in the outer for loop to 1 to see if that helps, you may also been to do the same for int x in the inner for loop...

Minecraft clone on java eclipse error

I watched a Youtube video of someone making a MineCraft clone, which compiled and ran without error. But when I copied it completely, I got an error.
The error is in the Render class: int pixels = new int(width * height);
Render:
package com.mads.minecraft.graphics;
public class Render {
public final int width;
public final int height;
public int[] pixels;
public Render(int width, int height){
this.width = width;
this.height = height;
int pixels = new int(width * height);
}
public void draw(Render render, int xOffset, int yOffset){
for (int y = 0; y < render.height; y++){
int yPix = y + yOffset;
if(yPix < 0 || yPix >= height) continue;
for (int x = 0; y < render.width; x++){
int xPix = x + xOffset;
if(xPix < 0 || xPix >= width) continue;
pixels[xPix + yPix + width] = render.pixels[x + y * render.width];
}
}
}
}
Display:
package com.mads.minecraft;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
import com.mads.minecraft.graphics.Screen;
public class Display extends Canvas implements Runnable{
static final long serialVersionUID = 1L;
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
public static final String TITLE = "Minecraft Alpha";
private Thread thread;
private boolean running = false;
private BufferedImage img;
private Screen screen;
private int[] pixels;
public Display(){
screen = new Screen(WIDTH, HEIGHT);
img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
}
public void start(){
if(running) return;
running = true;
thread = new Thread(this);
thread.start();
}
public void stop(){
if(!running) return;
running = false;
try {
thread.join();
} catch (Exception e){
e.printStackTrace();
System.exit(0);
}
}
public void run(){
while(running){
tick();
render();
}
}
public void tick(){}
public void render(){
BufferStrategy bs = getBufferStrategy();
if(bs == null){
createBufferStrategy(3);
return;
}
screen.render();
for (int i = 0; i < WIDTH * HEIGHT; i++){
pixels[i] = screen.pixels[i];
}
Graphics g = bs.getDrawGraphics();
g.drawImage(img, WIDTH, HEIGHT, null);
g.dispose();
bs.show();
}
public static void main(String []args){
Display game = new Display();
JFrame frame = new JFrame();
frame.add(game);
frame.pack();
frame.setTitle(TITLE);
frame.setSize(WIDTH, HEIGHT);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
game.start();
}
}
Screen:
package com.mads.minecraft.graphics;
import java.util.Random;
public class Screen extends Render{
private Render test;
public Screen(int width, int height) {
super(width, height);
Random random = new Random();
test = new Render(256, 256);
for(int i = 0; i < 256 * 256; i++) {
test.pixels[i] = random.nextInt();
}
}
public void render(){
draw(test, 0, 0);
}
}
Following is an invalid statement which you need to replace:
int pixels = new int(width * height); (int is a primitive data type not reference type, so you can not create an object)
by
pixels = new int[width * height]; (You can create an array of int. You have already declared the variable pixels at the instance level as int[], so no need to declare again)
Hope, this helps.
Apparently you're trying to initialize an array in Render. All you have to do is to replace int pixels = new int(width * height) in Renders constructor with this:
pixels = new int[width * height];

NullPointerException in my game, can't be fixed

I'm making an rpg with a custom pixel engine, and when I try to run it I just get a NullPointerException and I know why, but when I try to initialize that variable I get another one in a different location and I fix that and now it won't run at all and I still get a NullPointerException. This is the class that gets an error, and the console tells me that the error is on the line that says screen.render();
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import sprites.SpriteSheetLoader;
public class Game extends Canvas implements Runnable{
private static final long serialVersionUID = 1L;
public static final int HEIGHT = 120;
public static final int WIDTH = 120;
public static final int SCALE = 3;
public static final String NAME = "TypicalRPG";
public SpriteSheetLoader loader;
private BufferedImage img = new BufferedImage(WIDTH * SCALE, HEIGHT * SCALE, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
private boolean running = false;
private Screen screen = new Screen(WIDTH, HEIGHT, loader);
Random random = new Random();
public void start(){
running = true;
new Thread(this).start();
}
public static void main(String args[]){
Game game = new Game();
game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
JFrame jf = new JFrame(NAME);
jf.add(game);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.pack();
jf.setVisible(true);
jf.setResizable(true);
game.start();
}
public void run(){
while(running){
tick();
render();
try{
Thread.sleep(5);
}
catch(InterruptedException e){ e.printStackTrace(); }
}
}
public void stop(){ running = false; }
public void tick(){
screen.render(0, 0, 0, 16, 16);
}
public void render(){
BufferStrategy bs = getBufferStrategy();
if(bs == null){
createBufferStrategy(3);
requestFocus();
return;
}
for(int i = 0; i < screen.pixels.length; i++){
pixels[i] = screen.pixels[i];
}
Graphics g = bs.getDrawGraphics();
g.drawImage(img, 0, 0, getWidth(), getHeight(), null);
g.dispose();
bs.show();
}
public void init(){
BufferedImage sheet = null;
try {
sheet = ImageIO.read(Game.class.getResourceAsStream("res/tiles.png"));
}
catch (IOException e) {
e.printStackTrace();
}
loader = new SpriteSheetLoader(sheet);
screen = new Screen(WIDTH, HEIGHT, loader);
}
}
and this is the class that has render():
import sprites.SpriteSheetLoader;
public class Screen{
public int[] pixels;
private SpriteSheetLoader loader;
private int w, h;
int xoff = 0, yoff = 0;
public Screen(int w, int h, SpriteSheetLoader loader){
this.loader = loader;
this.w = w;
this.h = h;
pixels = new int[w * h];
}
public void render(int xpos, int ypos, int tile, int width, int height){
loader.grabTile(tile, width, height);
xpos -= xoff;
ypos -= yoff;
for(int y = 0; y < height; y++){
if(ypos + y < 0 || ypos + y >= h) continue;
for(int x = 0; x < width; x++){
if(xpos + x < 0 || xpos + x >= w) continue;
int col = loader.pixels[x + (y * height)];
if(col != -65281) pixels[(x + xpos) + (y + ypos)] = col;
}
}
}
}
Seems like you never initiate the loader in your first class.
You define your variables like this:
public SpriteSheetLoader loader;
private Screen screen = new Screen(WIDTH, HEIGHT, loader);
Hence, you pass a null-object to your Screen. And from there you try to call a method on that null-object:
loader.grabTile(tile, width, height);
You have only declared loader, but never initiated it.
public SpriteSheetLoader loader;

Categories