Прежде чем начать, вот моя UML-диаграмма:
Я пытаюсь анимировать персонажа моего плеера, но разделить на 5 отдельных файлов PNG. Я бы предпочел работать с 5 кадрами напрямую, потому что это не детальное изображение, а 8-битный символьный спрайт. Кроме того, я не знаю, как использовать много программ для редактирования фотографий, поэтому я использую отдельные файлы.
Я пробовал довольно много примеров из Stack Overflow и других учебных пособий, но, похоже, ничто не соответствует тому, что я пытаюсь сделать на платформе, которую я должен построить для своей игры. Это на конец семестра проекта, но я планирую продолжить после истечения срока и оставить его с открытым исходным кодом.
Вот мой код.
Driver. Загружает игровой цикл и другие функции.
package cactus;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
public class Driver extends Canvas implements Runnable{
private static final long serialVersionUID = 1L;
private Thread t;
private boolean running;
private Controller controller;
public Driver() {
controller = new Controller();
/*--- Add Game Objects ---------------------------------------*/
controller.addObject(new Travis(500, 675, ID.Travis));
/*------------------------------------------------------------*/
}
public synchronized void start() {
t = new Thread(this);
t.start();
running = true;
}
public synchronized void stop() {
try {
t.join();
running = false;
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
this.requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while(running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1) {
tick();
delta--;
}
if(running) {
render();
}
frames++;
if(System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("FPS:" + frames);
frames = 0;
}
}
stop();
}
private void tick() {
controller.tick();
}
private void render() {
BufferStrategy buffer = this.getBufferStrategy();
if (buffer == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = buffer.getDrawGraphics();
g.drawImage(background.getCurrentBG(), 0, 0, Frame.getWidth(), Frame.getHeight(), null);
controller.render(g);
g.dispose();
buffer.show();
}
public static void main(String[] args) {
new Driver();
}
}
контроллер. Перебирает игровые объекты, чтобы выполнить некоторые из их функций рендеринга, которые отображают то, на что они похожи, и их функции галочек, которые управляют их местоположением и некоторыми будущими действиями.
package cactus;
import java.awt.Graphics;
import java.util.LinkedList;
public class Controller {
LinkedList<Objects> gameObj = new LinkedList<Objects>();
public void tick() {
for (int i = 0; i < gameObj.size(); i++) {
Objects currentObject = gameObj.get(i);
if (currentObject.getId() == ID.ShootFire && currentObject.getX() > Frame.getWidth() + 30) {
removeObject(currentObject);
System.out.println("Fire Object Removed");
}
currentObject.tick();
}
}
public void render(Graphics g) {
for (int i = 0; i < gameObj.size(); i++) {
Objects currentObject = gameObj.get(i);
currentObject.render(g);
}
}
public void addObject(Objects o) {
this.gameObj.add(o);
}
public void removeObject(Objects o) {
this.gameObj.remove(o);
}
}
Класс игрока. Получает методы из класса абстрактных объектов
package cactus;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
// import javax.swing.Timer;
public class Travis extends Objects implements ActionListener{
ArrayList<BufferedImage> animation;
// Timer animationTimer;
Graphics g;
// int i = 0;
public Travis(int x, int y, ID id) {
super(x, y, id);
this.animation = createAnimation();
// this.animationTimer = createTimer(animationTimer);
// animationTimer.start();
}
private synchronized ArrayList<BufferedImage> createAnimation() {
animation = new ArrayList<BufferedImage>();
for (int i = 0; i < 6; i++) {
try {
animation.add(ImageIO.read(new File("./src/resources/image/travis/frame_" + i + ".png")));
} catch (IOException e) {e.printStackTrace(); System.exit(0);}
}
return animation;
}
// private synchronized Timer createTimer(Timer animationTimer) {
// animationTimer = new Timer(15, this);
// animationTimer.setDelay(15*1000);
// return animationTimer;
// }
@Override
public void tick() {
x += velocityX;
}
/*
* drawImage(img, posX, posY, observe [null])
*
* (non-Javadoc)
* @see cactus.GameObjects#render(java.awt.Graphics)
*/
@Override
public void render(Graphics g) {
for (int i = 0; i < 6; i++) {
g.drawImage(animation.get(i), x, y, null);
}
if (i == 6)
i = 0;
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
Я хочу, чтобы каждый объект ArrayList (хотя, вероятно, изменит его на Map), играл с разными задержками между кадрами.
* frame_0: 1s
* frame_1: 2s
* frame_2: 2s
* frame_3: 1s
* frame_4: 2s
* frame_5: 5 с
Я пытался использовать Таймер и некоторые другие вещи, и я не смог его оживить, он просто отображает последний кадр.
Мне не хватает представителя для публикации фотографий.