I've been trying to create a sprite for our game but the problem is when i tried to run the program this error appears
Exception in thread "main" java.awt.image.RasterFormatException: (y + height) is outside of Raster
at sun.awt.image.ByteInterleavedRaster.createWritableChild(Unknown Source)
at java.awt.image.BufferedImage.getSubimage(Unknown Source)
at really.sprite.TrueSprite.<init>(TrueSprite.java:31)
at really.sprite.Sprite.main(Sprite.java:13)
here's the program that causes the error:
public class TrueSprite
{
BufferedImage spriteSheet = ImageIO.read(new File("resources/robin.png"));
int width = 240, height = 314, rows = 5 , columns = 5;
BufferedImage[] sprites = new BufferedImage[rows * columns];
public TrueSprite(int width, int height, int rows, int columns) throws IOException
{
this.width = width;
this.height = height;
this.rows = rows;
this.columns = columns;
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < columns; j++)
{
sprites[(i * columns) + j ] = spriteSheet.getSubimage(i * width, j * height, width, height);
}
}
}
public void paint(Graphics g)
{
g.drawImage(sprites[1], 314, 240, null);
}
}
the image size I imported is 1200 x 1570.
Related
I've run this code this in the newest version of Eclipse but in that, it did not specify this error message but did point at the pixels[x + y * width] = Sprite.grass.pixels[(x & 15) + (y & 15) *Sprite.grass.SIZE]; line of the code. So I didn't know what was the error so I ran it on an older version of the IDE, Kepler. In the IDE it gave this error message. I searched a lot on stackoverflow, there were several cases where people got the error message but most of them were related to importing android.R or something of that sort. But I'm not doing this for any android application, this is just for a normal project. So none of the solutions matched my problem.
The error message is pointing towards pixels and SIZE in Sprite class. If you need the SpriteSheet class code too let me know. There I was trying to load an image. This is all I can explain for now. So could anyone help me out, please?
package com.thecherno.rain.graphics;
import java.util.Random;
public class Screen {
private int width, height;
public int[] pixels;
final int MAP_SIZE = 64;
final int MAP_SIZE_INT = MAP_SIZE - 1;
public int[] tiles = new int[MAP_SIZE * MAP_SIZE];
public Random random = new Random();
public Screen(int width, int height) {
this.width = width;
this.height = height;
pixels = new int[width * height];
for(int i = 0; i < MAP_SIZE * MAP_SIZE; i++) {
tiles[i] = random.nextInt(0xffffff);
tiles[0] = 0;
}
}
public void clear() {
for(int i = 0; i < pixels.length; i++) {
pixels[i] = 0;
}
}
public void render(int xoffset, int yoffset) {
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
pixels[x + y * width] = Sprite.grass.pixels[(x & 15) + (y & 15) *Sprite.grass.SIZE];
}
}
}
}
package com.thecherno.rain.graphics;
public class Sprite {
public final int SIZE;
private int x, y;
public int[] pixels;
private SpriteSheet sheet;
public static Sprite grass = new Sprite(16, 0, 0, SpriteSheet.tiles);
public Sprite(int size, int x, int y, SpriteSheet sheet) {
SIZE = size;
pixels = new int[SIZE * SIZE];
this.x = x * size;
this.y = y * size;
this.sheet = sheet;
load();
}
private void load() {
for(int y = 0; y < SIZE; y++) {
for(int x = 0; x < SIZE; x++) {
pixels[x + y * SIZE] = sheet.pixels[(x + this.x) + (y + this.y) * sheet.SIZE];
}
}
}
}
What I should get in the end is a grid with squares that have stable colors if I resize the window. So far I get a grid that has random colors but as the everything is redrawn the colors are too. I'm thinking, maybe an array that stores the colors could work but I don't really know how to implement it in what I have so far.
public class GridRandomColors extends JFrame {
private static class Board extends JPanel {
private Rectangle MAIN_RECT;
private double BRICK_WIDTH, BRICK_HEIGHT;
private int COLS = 8;
private int ROWS = 8;
public Board() {
setBackground(Color.gray);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
drawRectangle(g);
drawBricks(g);
}
private void drawRectangle(Graphics g) {
if (getHeight() > getWidth()) {
MAIN_RECT = new Rectangle(0, 0, getWidth(), getWidth());
g.fillRect(0, (getHeight()-getWidth())/2, getWidth(), getWidth());
x = 0;
y = (getHeight()-getWidth())/2;
} else {
x = (getWidth()-getHeight())/2;
y = 0;
MAIN_RECT = new Rectangle(0, 0, getHeight(), getHeight());
g.fillRect((getWidth()-getHeight())/2, 0, getHeight(), getHeight());
}
BRICK_WIDTH = (float) MAIN_RECT.getWidth() / COLS;
BRICK_HEIGHT = (float) MAIN_RECT.getHeight() / ROWS ;
}
double spacing = 0.2;
private double x;
private double y;
private Color color;
private void drawBricks(Graphics g) {
Graphics2D brick = (Graphics2D) g.create();
for (int j = 0; j < ROWS; j++) {
for (int a = 0; a < COLS; a++) {
Random rand = new Random();
color = new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat());
Color oldColor = g.getColor();
brick.setColor(color);
Rectangle2D.Double rect = new Rectangle2D.Double(x, y, BRICK_WIDTH - spacing*(COLS-1), BRICK_HEIGHT- spacing*(ROWS-1));
brick.fill(rect);
brick.setColor(oldColor);
x += BRICK_HEIGHT+spacing;
}
if (getHeight() > getWidth()) {
x = 0;
}
else {
x = (getWidth() - getHeight()) / 2;
}
y += BRICK_HEIGHT+spacing;
}
}
}
public GridRandomColors() {
setDefaultCloseOperation(EXIT_ON_CLOSE); //mai bine cu exit on close
setSize(800, 820);
add(new Board());
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new GridRandomColors().setVisible(true);
}
});
}
}
You can use a simple two dimensional array to store the colors and generate it in your constructor:
private static class Board extends JPanel {
// ...
private int COLS = 8;
private int ROWS = 8;
private Color[][] colors;
public Board() {
// ...
Random rand = new Random();
colors = new Color[ROWS][COLS];
for (int a = 0; a < ROWS; a++) {
for (int b = 0; b < COLS; b++) {
colors[a][b] = new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat());
}
}
}
private void drawBricks(Graphics g) {
// ...
for (int j = 0; j < ROWS; j++) {
for (int a = 0; a < COLS; a++) {
Color oldColor = g.getColor();
brick.setColor(colors[j][a]);
// ...
}
// ...
}
}
}
I have a class to separate and join image in tiles. It works fine when the sides of the tile correspond to the dimensions of the image, i.e. height 250, tile height 25. But when it's not it doesn't create smaller tiles at the borders as it should.
Where would be the problem to properly create the border tiles smaller than the rest?
Constructor:
public EdgeBufferedImage(BufferedImage image, int w, int h){
this.sourceImg = image;
this.setCol((int)Math.ceil(image.getWidth()/(double)w));
this.setRow((int)Math.ceil(image.getHeight()/(double)h));
this.setWidth(image.getWidth());
this.setHeight(image.getHeight());
this.setTilew(w);
this.setTileh(h);
this.setMatImg(new BufferedImage[row][col]);
}
Methods:
Image tiling
public void createSmallImages() {
int rows = getRow();
int columns = getCol();
int smallWidth = getTilew();
int smallHeight = getTileh();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (j == columns - 1) smallWidth = getWidth() - (getTilew() * j);
if (i == rows - 1) smallHeight = getHeight() - (getTileh() * i);
matImg[i][j] = getSourceImg().getSubimage(j * smallWidth, i
* smallHeight, smallWidth, smallHeight);
}
smallWidth = getTilew();
smallHeight = getTileh();
}
}
Image joining
public void joinTiles(){
int rows = getRow();
int columns = getCol();
int smallWidth = getTilew();
int smallHeight = getTileh();
BufferedImage comb = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) comb.getGraphics();
g.setColor(Color.RED);
for (int row = 0; row < rows; row++){
for (int col = 0; col < columns; col++){
BufferedImage piece = getMatImg()[row][col];
if (col == columns - 1) smallWidth = getWidth() - (getTilew() * col);
if (row == rows - 1) smallHeight = getHeight() - (getTileh() * row);
g.drawImage(piece, col * smallWidth, row * smallHeight, smallWidth, smallHeight, null);
g.drawRect(col * smallWidth, row * smallHeight, smallWidth, smallHeight);
}
smallWidth = getTilew();
smallHeight = getTileh();
}
g.dispose();
setSourceImg(comb);
}
Original image is 512*512
I've been trying to create a sprite to be used on our java game. Everything seems normal, i see no errors on my program but suddenly when it's to be run an error appeared that it Cannot be Instantiated. Can somebody tell me what's wrong with it?
#SuppressWarnings("unused")
public class TrueSprite
{
BufferedImage spriteSheet = ImageIO.read(new File("robin.png"));
int width = 240, height = 314, rows = 5 , columns = 5;
BufferedImage[] sprites = new BufferedImage[rows * columns];
public TrueSprite(int width, int height, int rows, int columns) throws IOException
{
this.width = width;
this.height = height;
this.rows = rows;
this.columns = columns;
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < columns; j++)
{
sprites[(i * columns) + j ] = spriteSheet.getSubimage(i * width, j * height, width, height);
}
}
}
public void paint(Graphics g)
{
g.drawImage(sprites[1], 100, 100, null);
}
}
here's the error:
load: really.sprite.TrueSprite.class can't be instantiated.
java.lang.InstantiationException: really.sprite.TrueSprite
at java.lang.Class.newInstance(Unknown Source)
at sun.applet.AppletPanel.createApplet(Unknown Source)
at sun.applet.AppletPanel.runLoader(Unknown Source)
at sun.applet.AppletPanel.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
First of all, you have no constructor, which is essential for your class to be instantiated. Put this inside your class declaration:
public TrueSprite() {
//code to run when your class is instantiated.
}
Now, this won't do anything special, but you can call it with:
TrueSprite sprite = new TrueSprite();
Additionally, your class needs to be cleaned up. Try putting your assignment code inside the constructor we just built, and the declaration to these variables outside of it:
#SuppressWarnings("unused")
public class TrueSprite
{
private final int width;
private final int height;
private final int rows;
private final int cols;
private BufferedImage bigImg;
private BufferedImage[] sprites;
public TrueSprite(int width, int height, int rows, int columns) {
this.width = width;
this.height = height;
this.rows = rows;
this.cols = columns;
this.bigImg = ImageIO.read(new File("robin.png"));
this.sprites = new BufferedImage[rows * cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
sprites[(i * cols) + j] = bigImg.getSubimage(j * width, i * height, width, height);
}
}
}
public void paint(Graphics g)
{
g.drawImage(sprites[1], 100, 100, null);
}
}
Just make sure you pass in four valid arguments into your TrueSprite constructor to call it correctly:
TrueSprite sprite = new TrueSprite(200, 500, 20, 50);
I think you need to create a non param constructor like
public TrueSprite() throws IOException
Your BufferedImage[] sprites = new BufferedImage[rows * columns]; outside the constructor initialised the sprites array with a size of 5*5=25. If you created a TrueSprit with a higher row or column, e.g. TrueSprite(100,100,100,100), the entries after sprites[24] will not be instantiated yet.
You should always place your initialisation inside the constructor. i.e.
private BufferedImage[] sprites;
public TrueSprite(int width, int height, int rows, int columns) throws IOException
{
this.width = width;
this.height = height;
this.rows = rows;
this.columns = columns;
this.sprites = new BufferedImage[rows * columns];
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < columns; j++)
{
sprites[(i * columns) + j ] = spriteSheet.getSubimage(i * width, j * height, width, height);
}
}
}
This will set the rows and columns to the correct value before creating your array with the values. Furthermore, you should have used a default constructor if you wanted to have default values. i.e.
public TrueSprite() throws IOException
{
this.width = 240;
this.height = 314;
this.rows = 5;
this.columns = 5;
this.sprites = new BufferedImage[rows * columns];
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < columns; j++)
{
sprites[(i * columns) + j ] = spriteSheet.getSubimage(i * width, j * height, width, height);
}
}
}
I have been working on a game via youtube tutorial, some of you may recognize it as the one presents by designsbyzephr and have run into an issue. I am fairly sure the code is correct as I have used the call before in a previous project. I am getting an array out of bounds exception even when using the full project source code posted on github. Any suggestions?
package Game;
import java.awt.BorderLayout;
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 javax.swing.JFrame;
import GFX.Screen;
import GFX.SpriteSheet;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 160;
public static final int HEIGHT = WIDTH / 12 * 9;
public static final int SCALE = 3;
public static final String NAME = "Game";
private JFrame frame;
public boolean running = false;
public int tickcount = 0;
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
private Screen screen;
public Game() {
setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
frame = new JFrame(NAME);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(this, BorderLayout.CENTER);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void init() {
screen = new Screen(WIDTH, HEIGHT, new SpriteSheet("/Sprites/spritesheet.png"));
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
screen.render(pixels, 0, WIDTH);
Graphics g = bs.getDrawGraphics();
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
g.dispose();
bs.show();
}
public synchronized void start() {
running = true;
new Thread(this).start();
}
public synchronized void stop() {
running = false;
}
public void run() {
long lastTime = System.nanoTime();
double nsPerTick = 1000000000D / 60D;
int ticks = 0;
int frames = 0;
long lastTimer = System.currentTimeMillis();
double delta = 0;
init();
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / nsPerTick;
lastTime = now;
boolean shouldRender = true;
while (delta >= 1) {
ticks++;
tick();
delta -= 1;
shouldRender = true;
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (shouldRender) {
frames++;
render();
}
if (System.currentTimeMillis() - lastTimer >= 1000) {
lastTimer += 1000;
frames = 0;
ticks = 0;
}
}
}
public void tick() {
tickcount++;
for (int i = 0; i < pixels.length; i++)
pixels[i] = i + tickcount;
}
public static void main(String[] args) {
new Game().start();
}
}
package GFX;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class SpriteSheet {
public String path;
public int width;
public int height;
public int[] pixels;
public SpriteSheet(String path) {
BufferedImage image = null;
try
{
image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path));
}
catch (IOException e)
{
e.printStackTrace();
}
if (image == null) return;
this.path = path;
this.width = image.getWidth();
this.height = image.getHeight();
pixels = image.getRGB(0, 0, width, height, null, 0, width);
for (int i = 0; i < pixels.length; i++) {
pixels[i] = (pixels[i] & 0xff) / 64;
}
for (int i = 0; i < 8; i++)
System.out.println(pixels[i]);
}
}
package GFX;
public class Screen {
public static final int MAP_WIDTH = 64;
public static final int MAP_WIDTH_MASK = MAP_WIDTH - 1;
public int[] tiles = new int[MAP_WIDTH * MAP_WIDTH];
public int[] colors = new int[MAP_WIDTH * MAP_WIDTH];
public int xOffset = 0;
public int yOffset = 0;
public int width;
public int height;
public SpriteSheet sheet;
public Screen(int width, int height, SpriteSheet sheet) {
this.width = width;
this.height = height;
this.sheet = sheet;
for (int i = 0; i < MAP_WIDTH * MAP_WIDTH; i++) {
colors[i * 4 + 0] = 0xff00ff;
colors[i * 4 + 1] = 0x00ffff;
colors[i * 4 + 2] = 0xffff00;
colors[i * 4 + 3] = 0x0000ff;
}
}
public void render(int[] pixels, int offset, int row) {
for (int yTile = yOffset >> 3; yTile <= (yOffset + height) >> 3; yTile++) {
int yMin = yTile * 8 - yOffset;
int yMax = yMin + 8;
if (yMin < 0)
yMin = 0;
if (yMin > height)
yMax = height;
for (int xTile = xOffset >> 3; xTile <= (xOffset + width) >> 3; xTile++) {
int xMin = xTile * 8 - xOffset;
int xMax = xMin + 8;
if (xMin < 0)
xMin = 0;
if (xMin > width)
xMax = width;
int tileIndex = (xTile & (MAP_WIDTH_MASK))
+ (yTile & (MAP_WIDTH_MASK)) * MAP_WIDTH;
for (int y = yMin; y < yMax; y++) {
int sheetPixel = ((y + yOffset) & 7) * sheet.width
+ ((xMin + xOffset) & 7);
int tilePixel = offset + xMin + y * row;
for (int x = xMin; x < xMax; x++) {
int color = tileIndex * 4 + sheet.pixels[sheetPixel++];
pixels[tilePixel++] = colors[color];
}
}
}
}
}
}
That is all the code so far. the error is as follows
Exception in thread "Thread-2" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at GFX.SpriteSheet.(SpriteSheet.java:22)
at Game.Game.init(Game.java:54)
at Game.Game.run(Game.java:91)
at java.lang.Thread.run(Unknown Source)
it is in this line
image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path));
your program cannot find file so it is returning null and a null pointer exception is thrown when you try and read from null
you need to make sure there is a file"/Sprites/spritesheet.png" relative to where you are running the program