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;
}
Related
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...
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];
Exception in thread "main" java.lang.IllegalArgumentException: n must be positive
at java.util.Random.nextInt(Unknown Source)
at net.survival_instincts.src.main.screenClass.<init>(screenClass.java:21)
at net.survival_instincts.src.main.windowClass.<init>(windowClass.java:28)
at net.survival_instincts.src.main.windowClass.main(windowClass.java:104)
CODE:
windowClass:
package net.survival_instincts.src.main;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import net.survival_instincts.src.graphics.renderClass;
import java.awt.image.*;
public class windowClass extends Canvas implements Runnable {
public static int WIDTH = 854;
public static int HEIGHT = 480;
private Thread thread;
private screenClass screen;
private BufferedImage img;
private boolean running = false;
private renderClass render;
private int[] pixels;
public windowClass() {
screen = new screenClass(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("Starting...");
}
#SuppressWarnings("unused")
private 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();
}
// Generates The Main Window
public static void main(String[] args) {
windowClass game = new windowClass();
JFrame frame = new JFrame();
frame.pack();
frame.setTitle("Survival Instincts v.0.01");
frame.setSize(WIDTH, HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(game);
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setVisible(true);
System.out.println("Initializing Startup...");
game.start();
}
public renderClass getRender() {
return render;
}
public void setRender(renderClass render) {
this.render = render;
}
}
renderClass:
package net.survival_instincts.src.graphics;
public class renderClass {
public static int width;
public static int height;
public final int[] pixels;
public renderClass(int width, int height) {
renderClass.width = width;
renderClass.height = height;
pixels = new int[width * height];
}
public void draw(renderClass render, int xOffset, int yOffset) {
for (int y = 0; y < renderClass.height; y++) {
int yPix = y + yOffset;
for (int x = 0; x < renderClass.width; x++) {
int xPix = x + xOffset;
pixels[xPix + yPix * width] = render.pixels[x + y * renderClass.width];
}
}
}
}
screenClass:
package net.survival_instincts.src.main;
import java.util.Random;
import net.survival_instincts.src.graphics.renderClass;
public class screenClass extends renderClass {
public renderClass test;
public screenClass(int width, int height){
super(width, height);
Random random = new Random();
test = new renderClass(256, 256);
for (int i = 0; i <65536; i++){
test.pixels[i] = random.nextInt(i);
}
}
public void render(){
draw(test, width, height);
}
}
Your are getting this error because Random.nextInt(0) will throw an exception. The value passed to nextInt() must be positive.
To correct this, you'll need to start your loop at i = 1.
Random.nextInt() needs a number that is positive, and in this for loop you are calling it with 0:
for (int i = 0; i <65536; i++){
test.pixels[i] = random.nextInt(i); // it will call random.nextInt(0)
}
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.
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;