Hey guys,
I’ve been lurking about on these forums for some time now, and just now decided to register, because no amount of searching and trail and error would yield and answer to me.
So I’m trying to make a simple WormChase game(Like the one in “Killer Game Programming in Java”), but I can’t really get the speed of my snake to be independent of how many times I call the snakes tick() function. So I’d love some help on this.
Also, I’m trying to paint is bodypart of the snake so that they just barely touch each other(I suspect this’ll be a problem when trying to adjust move speed), because I want to try and add graphics to the snake(Using sprites). Some help on how to position the body parts would be awesome too(Or rather, how to calculate the new position of the head)
My 2 classes are here:
WormChase.java
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class WormChase extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
private static final String GAME_TITLE = "WormChase";
private static final int WIDTH = 500;
private static final int HEIGHT = 400;
private boolean isRunning = false;
private volatile boolean isPaused = false;
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
private int frames = 0, fps = 0;
private int ticks = 0, tps = 0;
private Worm bob;
private void start() {
isRunning = true;
new Thread(this).start();
}
public void run() {
init();
long lastLoopTime = System.nanoTime();
double unprocessed = 0;
double nsPerTick = 1000000000.0 / 10.0;
long fpsTimer = lastLoopTime;
while (isRunning) {
long now = System.nanoTime();
unprocessed += (now - lastLoopTime) / nsPerTick;
long delta = now - lastLoopTime;
lastLoopTime = now;
while (unprocessed >= 1) {
unprocessed--;
tick(delta);
}
render();
if (System.nanoTime() - fpsTimer > 1000000000) {
fps = frames;
frames = 0;
tps = ticks;
ticks = 0;
fpsTimer += 1000000000;
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.exit(0);
}
private void init() {
bob = new Worm(WIDTH, HEIGHT, 1f, 40);
}
private void tick(long delta) {
if (!isPaused) {
// move bob
bob.tick(delta);
// Update tick counter
ticks++;
}
}
private void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawImage(image, 0, 0, WIDTH, HEIGHT, null);
// draw bob
bob.render(g);
// draw fps/ticks
g.setColor(Color.white);
g.drawString("fps: " + fps + " ticks:" + tps, 20, 25);
g.dispose();
bs.show();
// Update frame counter
frames++;
}
/**
* Toggles the state of pause
*/
public void togglePauseState() {
isPaused = !isPaused;
}
public void testPress(int x, int y) {
togglePauseState();
}
public static void main(String[] args) {
final WormChase wc = new WormChase();
wc.setPreferredSize(new Dimension(WIDTH, HEIGHT));
wc.setMaximumSize(new Dimension(WIDTH, HEIGHT));
wc.setMinimumSize(new Dimension(WIDTH, HEIGHT));
wc.setIgnoreRepaint(true);
JFrame frame = new JFrame(GAME_TITLE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container v = frame.getContentPane();
v.add(wc);
frame.pack();
frame.setFocusable(true);
frame.requestFocus();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
wc.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
// System.out.println("You clicked, master.");
wc.testPress(e.getX(), e.getY());
}
});
wc.start();
}
}
And Worm.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Point2D;
import java.util.Random;
public class Worm {
private static Random random = new Random();
private static final int DOTSIZE = 12;
private final int MAX_SIZE;
private final int w, h;
private Point2D.Double[] wormBody;
private int curDir;
private int curSize = 0;
private int tailPos = -1;
private int headPos = -1;
private float speed;
public Worm(int w, int h, float speed, int max_size) {
this.w = w;
this.h = h;
this.speed = speed;
MAX_SIZE = max_size;
wormBody = new Point2D.Double[MAX_SIZE];
curDir = random.nextInt(360);
}
public void render(Graphics g) {
if (curSize > 0) {
g.setColor(Color.gray);
int i = tailPos;
while (i != headPos) {
g.fillOval((int)wormBody[i].x, (int)wormBody[i].y, DOTSIZE, DOTSIZE);
i = (i + 1) % MAX_SIZE;
}
g.setColor(Color.red);
g.fillOval((int)wormBody[headPos].x, (int)wormBody[headPos].y, DOTSIZE, DOTSIZE);
}
}
public void tick(long delta) {
int prevPos = headPos;
headPos = (headPos + 1) % MAX_SIZE; // Wrapping if needed
if (curSize == 0) {
wormBody[headPos] = new Point2D.Double(w / 2, h / 2);
curSize++;
tailPos = headPos;
} else if (curSize == MAX_SIZE) {
wormBody[headPos] = newPos(prevPos, delta);
tailPos = (tailPos + 1) % MAX_SIZE;
} else {
wormBody[headPos] = newPos(prevPos, delta);
curSize++;
}
}
/**
* This is where the new head position is being calculated.
*/
private Point2D.Double newPos(int prevPos, long delta) {
double ds = delta / 10000000D * speed;
double dirInRad = Math.toRadians(curDir);
double x = wormBody[prevPos].x + Math.cos(dirInRad) * ds + Math.cos(dirInRad) * (DOTSIZE-2);
double y = wormBody[prevPos].y + Math.sin(dirInRad) * ds + Math.sin(dirInRad) * (DOTSIZE-2);
if (x < 0) {
x += w;
} else if (x >= w) {
x -= w;
}
if (y < 0) {
y += h;
} else if (y >= h) {
y -= h;
}
curDir += random.nextInt(90) - 45;
return new Point2D.Double(x, y);
}
public boolean touchedHead(int x, int y) {
return false;
}
public boolean touchedBody(int x, int y) {
return false;
}
}
Any help would be awesome!