Wednesday, May 28, 2014

Thursday, May 15, 2014

I solved *my* problem...

Turns out my problem was just a minor issue -- I put "Sprite.sheet.SIZE" when it should have just been "sheet.SIZE".  :sigh:

Anyway, here's my Sprite class if you are interested:
package com.version001.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); // Sprite.grass is 16x16 and in column 0, row 0

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

Wednesday, May 14, 2014

Episode 20

Once we complete Episode 20 I will post the code here.

The following sprite sheets include an original "blank" sheet showing 16x16 sprites on a 256x256 pixel grid as well as one with a "grass" texture and a "water" texture.
The following code makes up our program so far:
GAME:

package com.version001.rain;

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 com.version001.rain.graphics.Screen;
import com.version001.rain.input.Keyboard;

public class Game extends Canvas implements Runnable {
 private static final long serialVersionUID = 1L;

 public static int width = 300;
 // public static int height = width / 16 * 9;
 public static int height = 168;
 public static int scale = 3;
 public static String title = "Rain";


 private Thread thread;
 private JFrame frame;
 private Keyboard key;
 private boolean running = false;

 private Screen screen;

 private BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //creating image
 private int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData(); //accessing image

 public Game() {
  Dimension size = new Dimension(width * scale, height * scale);
  setPreferredSize(size);

  screen = new Screen(width, height);
  frame = new JFrame();
  key = new Keyboard();

  addKeyListener(key);

 }

 public synchronized void start() {
  running = true;
  thread = new Thread(this, "Display");
  thread.start();
 }

 public synchronized void stop() {
  running = false;
  try {
   thread.join();
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }


 public void run() {
  long lastTime = System.nanoTime();
  long timer = System.currentTimeMillis();
  final double ns = 1000000000.0 / 60.0;
  double delta = 0;
  int frames = 0;
  int updates = 0;
  while (running) {
   long now = System.nanoTime();
   delta += (now-lastTime) / ns;
   lastTime = now;
   while (delta >= 1) {
    update();
    updates++;
    delta--;
   }
   render();
   frames++;

   if(System.currentTimeMillis() - timer > 1000) {
    timer += 1000;
    System.out.println(updates + " ups " + frames + " fps");
    frame.setTitle(title + "  |  " + updates + " ups " + frames + " fps");
    updates = 0;
    frames = 0;
   }
  }
  stop();
 }

 int x = 0, y = 0;

 public void update() { 
  key.update();
  if (key.up) y--;
  if (key.down) y++;
  if (key.left) x--;
  if (key.right) x++;  
 }

 public void render() {
  BufferStrategy bs = getBufferStrategy();
  if (bs == null) {
   createBufferStrategy(3);
   setFocusable(true);  // ADD THIS TO MAKE KEYS WORK!
   return;
  }

  screen.clear();
  screen.render(x, y);

  for (int i = 0; i < pixels.length; i++) {
   pixels[i] = screen.pixels[i];
  }

  Graphics g = bs.getDrawGraphics();
  g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
  g.dispose();
  bs.show();
 }

 public static void main(String[] args) {
  Game game = new Game();
  game.frame.setResizable(false);
  game.frame.setTitle(Game.title);
  game.frame.add(game);
  game.frame.pack();
  game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  game.frame.setLocationRelativeTo(null);
  game.frame.setVisible(true);

  game.start();
 }
}

Screen:
package com.version001.rain.graphics;

import java.util.Random;

public class Screen {

 private int width, height;
 public int[] pixels;
 public final int MAP_SIZE = 64;
 public final int MAP_SIZE_MASK = MAP_SIZE - 1;

 public int[] tiles = new int[MAP_SIZE * MAP_SIZE];

 private 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++) {
   int yy = y + yOffset;
   //if (yy < 0 || yy >= height) break;
   for (int x = 0; x < width; x++) {
    int xx = x + xOffset;
    //if (xx < 0 || xx >= width) break;
    int tileIndex = ((xx >> 4) & MAP_SIZE_MASK) + ((yy >> 4) & MAP_SIZE_MASK) * MAP_SIZE;
    pixels[x + y * width] = tiles[tileIndex];


   }
  }
 }
}

Keyboard:
package com.version001.rain.input;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Keyboard implements KeyListener {

 private boolean[] keys = new boolean[120];
 public boolean up, down, left, right;

 public void update() {
  up = keys[KeyEvent.VK_UP] || keys[KeyEvent.VK_W];
  down = keys[KeyEvent.VK_DOWN] || keys[KeyEvent.VK_S];
  left = keys[KeyEvent.VK_LEFT] || keys[KeyEvent.VK_A];
  right = keys[KeyEvent.VK_RIGHT] || keys[KeyEvent.VK_D];

  for (int i = 0; i < keys.length; i++){
   if (keys[i]){
    System.out.println("KEY: " + i);
   }
  }
 }

 public void keyPressed(KeyEvent e) {
  keys[e.getKeyCode()] = true;
 }

 public void keyReleased(KeyEvent e) {
  keys[e.getKeyCode()] = false;
 }

 public void keyTyped(KeyEvent e) {

 }

}

SpriteSheet:
package com.version001.rain.graphics;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;

public class SpriteSheet {

 private String path;
 final int SIZE;
 public int[] pixels;

 public SpriteSheet(String path, int size){
  this.path = path;
  SIZE = size;
  pixels = new int[SIZE * SIZE];
  load();
 }

 private void load() {
  try {
   BufferedImage image = ImageIO.read(SpriteSheet.class.getResource(path));
   int w = image.getWidth();
   int h = image.getHeight();
   image.getRGB(0, 0, w, h, pixels, 0, w);
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

Sprite:
package com.version001.rain.graphics;

public class Sprite {

 private final int SIZE;

 private int x, y;
 public int[] pixels;
 private SpriteSheet sheet;

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