电子游戏最重要的表现形式我认为是动作。当然精美的立绘也可以给人非常棒的感官体验,但是能动的角色往往更能让人有心驰神往的感觉。这篇文章我将借助JavaFX让精灵动起来。
动画实体类
动画实体类主要存放动画的每一帧,以及长宽和位置信息等等基础信息。
与之前的图片类不同的是,我们定义了一个图片指针,指向将要绘制的下一帧信息。
@Data
@NoArgsConstructor
// 动画实体
public class AnimEntity {
// 图片集合
private List<Image> frame;
// 动画指针
private int frameIdx;
// 图片的长宽
private int height;
private int width;
// 位置
private int posx;
private int posy;
public AnimEntity(List<String> imagename, int width, int height, int posx, int posy){
this.width = width;
this.height = height;
this.posx = posx;
this.posy = posy;
this.frameIdx = 0;
frame = new ArrayList<>();
for(int i=0; i<imagename.size(); i++){
frame.add(new Image(imagename.get(i), width, height, true, true));
}
}
// 播放下一帧
public Image getnext(){
Image framenow = frame.get(frameIdx++);
if(frameIdx == frame.size()){
frameIdx = 0;
}
return framenow;
}
}
动画画家
动画画家存储了所有将要绘制到画布上的信息,并且按照顺序将他们绘制出来
public class AnimDrawer {
private Canvas canvas;
private GraphicsContext gc;
// 动画集合
private List<AnimEntity> animlist;
public AnimDrawer(Canvas canvas, GraphicsContext gc){
this.canvas = canvas;
this.gc = gc;
animlist = new ArrayList<>();
}
// 添加动画实体
public void addAnim(AnimEntity animEntity){
this.animlist.add(animEntity);
}
// 移除动画实体
public void removeAnim(AnimEntity animEntity){
this.animlist.remove(animEntity);
}
// 开始不停画动画
public void start(int timeout){
new Thread(()->{
while (true) {
draw();
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
// 在画布上画动画
public void draw(){
if(animlist.size() == 0){
throw new RuntimeException("没有动画呀");
}
gc.clearRect(0,0,canvas.getWidth(), canvas.getHeight());
for(int i=0; i<animlist.size(); i++){
//System.out.println("aaa");
gc.drawImage(animlist.get(i).getnext(),
animlist.get(i).getPosx(), animlist.get(i).getPosy(),
animlist.get(i).getWidth(), animlist.get(i).getHeight());
}
}
}
主启动类
主启动类加载动画资源,并且调用画家类,将所有的动画绘制到画布上
public class MainStage extends Application {
public static void main(String[] args) {
launch(args);
}
// 读取文件夹下面的所有图片
public List<String> getnamelist(String sufix){
String path = "/workspace/JAVAFXGame/target/classes/image/" + sufix;
File file = new File(path);
String[] filelist = file.list();
List<String> namelist = new ArrayList<>();
for(int i=0; i<filelist.length; i++){
namelist.add("/image/" + sufix + "/" + filelist[i]);
}
return namelist;
}
@Override
public void start(Stage primaryStage) throws Exception {
Canvas canvas = new Canvas(300,300);
GraphicsContext gc = canvas.getGraphicsContext2D();
AnimDrawer animDrawer = new AnimDrawer(canvas, gc);
// 创建动画
List<String> namelist = getnamelist("role");
List<String> namelist1 = getnamelist("role1");
AnimEntity animEntity = new AnimEntity(namelist, 150, 150, 50, 100);
AnimEntity animEntity1 = new AnimEntity(namelist1, 150,150, 150,100);
animDrawer.addAnim(animEntity);
animDrawer.addAnim(animEntity1);
animDrawer.start(50);
Pane pane = new Pane();
Scene scene = new Scene(pane, 300,300);
pane.getChildren().add(canvas);
primaryStage.setScene(scene);
primaryStage.show();
}
}
效果展示
动画素材
动画素材有点多,我就一次全放上来了。
首先是走路的。
然后是原地休息的。