Good day, me hearties!
Let’s get straight to it. I’ve made a game that’s composed of three class files: Game.java, Screen.java, and Map.java.
Game.java: game loop, etc
Screen.java: renders a map
Map: the map
Alright. Pretty basic, eh? Right. That’s what I was hoping for.
Issue starts here: THE SCREEN IS SCALED AFTER RENDERING PROCESS COMPLETES IN ORDER TO SAVE CPU POWER.
Not much of a problem, it seems. Well, read on.
In order to calculate the width/height (in pixels) of my tile-map, I simply multiplied the tile size by the width/height in tiles. This would be accurate, but after the scaling (x3), this data is completely wrong. A coordinate before the scaling doesn’t represent the same thing it did after the scaling. I implemented a player & camera, not realizing that my coordinate system was entirely nullified, and I began experiencing many issues, such as not being able to calculate when the player reaches the edge of the map.
Keep in mind that the player was a BufferedImage rendered on top of the Screen/Map (also a BufferedImage).
How can I retain this scale and accurately implement a coordinate system? Should I somehow merge the player image into the map image, resulting in both items being scaled? This seems sensible, yet how would I carry it out?
Game.java:
package com.mizzath.game;
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.mizzath.graphics.*;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
int width = 300;
int height = width / 12 * 9;
int scale = 3;
String title = "Game";
boolean running = false;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
JFrame frame;
Thread thread;
Screen screen;
Map map;
public Game() {
frame = new JFrame(title);
map = new Map(64, 64, 16);
screen = new Screen(width, height, map);
Dimension size = new Dimension(width * scale, height * scale);
setSize(size);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(this);
frame.pack();
frame.setVisible(true);
start();
}
public void run() {
long start = System.nanoTime();
long timer = System.currentTimeMillis();
double period = 1000000000D / 60D;
double delta = 0;
int updates = 0; // Logic
int frames = 0; // Rendering
while(running) {
long now = System.nanoTime();
delta += (now - start) / period;
start = now;
if (delta > 1) {
updates++;
update();
delta--;
}
frames++;
render();
if (System.currentTimeMillis() - timer > 1000) {
frame.setTitle(title + " | Logical updates: " + updates + ", Graphical Updates: " + frames);
timer += 1000;
updates = 0;
frames = 0;
}
}
}
public void render() {
BufferStrategy strategy = getBufferStrategy();
if (strategy == null) {
createBufferStrategy(3);
return;
}
screen.render(0, 0);
for (int i = 0; i < pixels.length; i++) {
pixels[i] = screen.pixels[i];
}
Graphics g = strategy.getDrawGraphics();
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
g.dispose();
strategy.show();
}
public void update() {
}
public void start() {
running = true;
thread = new Thread(this, "Display");
thread.start();
}
public void stop() {
running = false;
try {
thread.join();
} catch (InterruptedException e) {
}
}
public static void main(String[] args) {
Game game = new Game();
}
}
Screen.java:
package com.mizzath.graphics;
public class Screen {
private int width, height;
private Map map;
public int[] pixels;
public Screen(int width, int height, Map map) {
this.width = width;
this.height = height;
this.map = map;
pixels = new int[width * height];
}
public void render(int xOffset, int yOffset) {
for (int y = 0; y < height; y++) {
int yy = y + yOffset;
if (yy < 0 || yy >= map.heightInPixels()) break;
for (int x = 0; x < width; x++) {
int xx = x + xOffset;
if (xx < 0 || xx >= map.widthInPixels()) break;
int tileIndex = (xx >> (map.tileSize() / 4)) + (yy >> (map.tileSize() / 4)) * map.widthInTiles();
if (tileIndex < map.tiles().length) {
pixels[x + y * width] = map.tiles()[tileIndex];
}
}
}
}
}
Map.java:
package com.mizzath.graphics;
import java.util.Random;
public class Map {
private int widthInTiles, heightInTiles, tileSize;
private int[] tiles;
private Random random = new Random();
public Map(int widthInTiles, int heightInTiles, int tileSize) {
this.widthInTiles = widthInTiles;
this.heightInTiles = heightInTiles;
this.tileSize = tileSize;
tiles = new int[widthInTiles * heightInTiles];
for (int i = 0; i < tiles.length; i++) {
tiles[i] = random.nextInt(0xffffff);
}
}
public int[] tiles() {
return tiles;
}
public int tileSize() {
return tileSize;
}
public int widthInTiles() {
return widthInTiles;
}
public int heightInTiles() {
return heightInTiles;
}
public int widthInPixels() {
return widthInTiles * tileSize;
}
public int heightInPixels() {
return heightInTiles * tileSize;
}
}
Thanks, mates!