Got example 2 working
Player input; and a different way of setting up the renderer
This commit is contained in:
parent
bca92faa88
commit
117589b17b
@ -38,7 +38,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>nz.ac.massey.javaecs</groupId>
|
<groupId>nz.ac.massey.javaecs</groupId>
|
||||||
<artifactId>javaecs</artifactId>
|
<artifactId>javaecs</artifactId>
|
||||||
<version>0.9.2-PRERELEASE</version>
|
<version>0.9.9-RELEASE_CANDIDATE</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
|
BIN
demo2/sprite.png
Normal file
BIN
demo2/sprite.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -1,22 +1,121 @@
|
|||||||
package nz.ac.massey.javaecs.examples;
|
package nz.ac.massey.javaecs.examples;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
import javafx.scene.Group;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.stage.Stage;
|
||||||
import nz.ac.massey.javaecs.Engine;
|
import nz.ac.massey.javaecs.Engine;
|
||||||
|
import nz.ac.massey.javaecs.Entity;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Control;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Input;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Render;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Sprite;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Vec2D;
|
||||||
|
import nz.ac.massey.javaecs.examples.Systems.ControlSystem;
|
||||||
|
import nz.ac.massey.javaecs.examples.Systems.PlayerSystem;
|
||||||
|
import nz.ac.massey.javaecs.examples.Systems.RenderSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hello world!
|
* Hello world!
|
||||||
*/
|
*/
|
||||||
public final class App {
|
public class App {
|
||||||
private App() {
|
static App thisApp;
|
||||||
|
public App() {
|
||||||
|
thisApp = this;
|
||||||
}
|
}
|
||||||
|
static Engine gameEngine;
|
||||||
|
public static Stage worldStage;
|
||||||
|
public static Group worldGroup;
|
||||||
|
static Integer syncManager = 0;
|
||||||
|
static Semaphore rendererFinished = new Semaphore(0);
|
||||||
/**
|
/**
|
||||||
* Says hello to the world.
|
* Says hello to the world.
|
||||||
* @param args The arguments of the program.
|
* @param args The arguments of the program.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) throws Exception{
|
||||||
Engine gameEngine = new Engine();
|
/************************************
|
||||||
|
** Initialise engine **
|
||||||
|
*************************************/
|
||||||
|
gameEngine = new Engine(16384);
|
||||||
|
|
||||||
|
/************************************
|
||||||
|
** Register game components **
|
||||||
|
*************************************/
|
||||||
|
gameEngine.registerComponent(Control.class);
|
||||||
|
gameEngine.registerComponent(Render.class);
|
||||||
|
gameEngine.registerComponent(Sprite.class);
|
||||||
|
gameEngine.registerComponent(Vec2D.class);
|
||||||
|
gameEngine.registerComponent(Input.class);
|
||||||
|
|
||||||
|
|
||||||
System.out.println("Hello World!");
|
/************************************
|
||||||
|
** Register and initialise systems **
|
||||||
|
*************************************/
|
||||||
|
ControlSystem controlSystem = new ControlSystem(gameEngine);
|
||||||
|
gameEngine.registerSystem(ControlSystem.class, controlSystem);
|
||||||
|
|
||||||
|
RenderSystem renderSystem = new RenderSystem(gameEngine, 10.);
|
||||||
|
gameEngine.registerSystem(RenderSystem.class, renderSystem);
|
||||||
|
|
||||||
|
PlayerSystem playerSystem = new PlayerSystem(gameEngine);
|
||||||
|
gameEngine.registerSystem(PlayerSystem.class, playerSystem);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************
|
||||||
|
** Create known entities **
|
||||||
|
*************************************/
|
||||||
|
// Input controller - gets player input
|
||||||
|
Entity inputEntity = gameEngine.createEntity();
|
||||||
|
gameEngine.addComponent(inputEntity, Input.class, new Input());
|
||||||
|
|
||||||
|
Entity playerEntity = gameEngine.createEntity();
|
||||||
|
gameEngine.addComponent(playerEntity, Vec2D.class, new Vec2D(25,25));
|
||||||
|
gameEngine.addComponent(playerEntity, Render.class, new Render(Sprite.class));
|
||||||
|
gameEngine.addComponent(playerEntity, Control.class, new Render(Control.class));
|
||||||
|
// Load the sprite
|
||||||
|
System.err.println(System.getProperty("user.dir"));
|
||||||
|
Image image = new Image(new FileInputStream("sprite.png"));
|
||||||
|
gameEngine.addComponent(playerEntity, Sprite.class, new Sprite(image, 50, 50));
|
||||||
|
// Push rendering into its own thread (to meet the design principle of a JavaFX program)
|
||||||
|
Thread renderThread = new Thread(new RenderStarter());
|
||||||
|
renderThread.start();
|
||||||
|
|
||||||
|
|
||||||
|
// Use a semaphore to block until the renderer is set-up
|
||||||
|
rendererFinished.acquire();
|
||||||
|
|
||||||
|
/************************************
|
||||||
|
** Run init() on the systems **
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
controlSystem.init(worldStage);
|
||||||
|
playerSystem.init(inputEntity);
|
||||||
|
renderSystem.init(worldGroup);
|
||||||
|
|
||||||
|
double dt = 0.001;
|
||||||
|
double frameRate = 1.0 / 144; // 1 second divided by target number of frames
|
||||||
|
|
||||||
|
boolean exit = false;
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
int state = 0;
|
||||||
|
|
||||||
|
while (!exit){
|
||||||
|
// Run system updates
|
||||||
|
controlSystem.update(dt);
|
||||||
|
playerSystem.update(dt);
|
||||||
|
renderSystem.update(dt);
|
||||||
|
|
||||||
|
dt = (System.nanoTime() - startTime) / 1e9; // convert nanoseconds to seconds
|
||||||
|
startTime = System.nanoTime();
|
||||||
|
if (dt < frameRate){
|
||||||
|
Thread.sleep((int)((frameRate-dt)*1000));
|
||||||
|
dt = (System.nanoTime() - startTime) / 1e9;
|
||||||
|
startTime = System.nanoTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderThread.join(); // Wait for any render task to exit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package nz.ac.massey.javaecs.examples.Components;
|
package nz.ac.massey.javaecs.examples.Components;
|
||||||
|
|
||||||
public class Control {
|
public class Control {
|
||||||
|
public int input = -1;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package nz.ac.massey.javaecs.examples.Components;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class Input {
|
||||||
|
// As this is a user-input- (i.e. timeframe in 10's or 100's of milliseconds) -derived value, the performance impact of
|
||||||
|
// AtomicInteger is irrelevant compared to its synchronisation ability.
|
||||||
|
public AtomicInteger input = new AtomicInteger(-1);
|
||||||
|
}
|
@ -3,5 +3,13 @@ package nz.ac.massey.javaecs.examples.Components;
|
|||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
|
|
||||||
public class Sprite {
|
public class Sprite {
|
||||||
Image sprite;
|
public Image sprite;
|
||||||
|
public Integer height;
|
||||||
|
public Integer width;
|
||||||
|
|
||||||
|
public Sprite(Image sprite, int height, int width){
|
||||||
|
this.sprite = sprite;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package nz.ac.massey.javaecs.examples;
|
||||||
|
|
||||||
|
|
||||||
|
import javafx.application.Application;
|
||||||
|
import javafx.scene.Group;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
public class JFXView extends Application {
|
||||||
|
public static Group root;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Stage primaryStage) throws Exception {
|
||||||
|
primaryStage.setTitle("JavaECS Demo 2");
|
||||||
|
App.worldGroup = new Group();
|
||||||
|
App.worldStage = primaryStage;
|
||||||
|
Scene scene = new Scene(App.worldGroup, 1024, 1024, Color.BLACK);
|
||||||
|
primaryStage.setScene(scene);
|
||||||
|
primaryStage.show();
|
||||||
|
// Notifiy that the renderer is ready
|
||||||
|
App.rendererFinished.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void run(){
|
||||||
|
launch(new String[0]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package nz.ac.massey.javaecs.examples;
|
||||||
|
|
||||||
|
import javafx.scene.Group;
|
||||||
|
|
||||||
|
// Add a renderer
|
||||||
|
public class RenderStarter implements Runnable{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
JFXView.run();
|
||||||
|
}
|
||||||
|
void updateScene(Group newGroup){
|
||||||
|
JFXView.root.getChildren().clear();
|
||||||
|
JFXView.root.getChildren().add(newGroup);
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,81 @@
|
|||||||
package nz.ac.massey.javaecs.examples.Systems;
|
package nz.ac.massey.javaecs.examples.Systems;
|
||||||
|
|
||||||
|
import java.util.BitSet;
|
||||||
|
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
|
import javafx.stage.Stage;
|
||||||
import nz.ac.massey.javaecs.ECSSystem;
|
import nz.ac.massey.javaecs.ECSSystem;
|
||||||
|
import nz.ac.massey.javaecs.Engine;
|
||||||
|
import nz.ac.massey.javaecs.Entity;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Control;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Input;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Render;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The control system creates a handler for input in the world stage.
|
||||||
|
* It then passes input events as they occur to the Input component
|
||||||
|
* The ControlSystem reads this input every frame update and enacts
|
||||||
|
* on the player controller
|
||||||
|
*/
|
||||||
public class ControlSystem extends ECSSystem {
|
public class ControlSystem extends ECSSystem {
|
||||||
|
Engine gameEngine;
|
||||||
|
Entity inputEntity;
|
||||||
|
|
||||||
|
public ControlSystem(Engine gamEngine){
|
||||||
|
this.gameEngine = gamEngine;
|
||||||
|
registrationSet = new BitSet();
|
||||||
|
registrationSet.set(gameEngine.getComponentIndex(Input.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(Stage world) {
|
||||||
|
// use a single entity to control inputs, it is present in the world stage
|
||||||
|
// and is responsible for collecting & passing data
|
||||||
|
inputEntity = entities.iterator().next();
|
||||||
|
|
||||||
|
// Add an event handler to the stage. This
|
||||||
|
Platform.runLater(new Runnable(){
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
world.addEventHandler(KeyEvent.KEY_PRESSED, (key) -> {
|
||||||
|
if(key.getCode()==KeyCode.W) {
|
||||||
|
updateKeyPress(0);
|
||||||
|
System.err.println("W pressed");
|
||||||
|
}
|
||||||
|
else if(key.getCode()==KeyCode.S) {
|
||||||
|
updateKeyPress(1);
|
||||||
|
System.err.println("S pressed");
|
||||||
|
}
|
||||||
|
else if(key.getCode()==KeyCode.A) {
|
||||||
|
updateKeyPress(2);
|
||||||
|
System.err.println("A pressed");
|
||||||
|
}
|
||||||
|
else if(key.getCode()==KeyCode.D) {
|
||||||
|
updateKeyPress(3);
|
||||||
|
System.err.println("D pressed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void update(double dt) {
|
||||||
|
//Input inputUpdate = (Input)gameEngine.getComponentData(inputEntity, Input.class);
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Updates the input's keypressed state
|
||||||
|
protected void updateKeyPress(int dir){
|
||||||
|
Input inputUpdate = (Input)gameEngine.getComponentData(inputEntity, Input.class);
|
||||||
|
inputUpdate.input.set(dir);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void init() throws Exception {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
package nz.ac.massey.javaecs.examples.Systems;
|
||||||
|
|
||||||
|
import java.util.BitSet;
|
||||||
|
|
||||||
|
import nz.ac.massey.javaecs.ECSSystem;
|
||||||
|
import nz.ac.massey.javaecs.Engine;
|
||||||
|
import nz.ac.massey.javaecs.Entity;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Control;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Input;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Sprite;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Vec2D;
|
||||||
|
|
||||||
|
public class PlayerSystem extends ECSSystem{
|
||||||
|
Engine gameEngine;
|
||||||
|
Entity inputEntity; // Entity which recieves event data
|
||||||
|
|
||||||
|
|
||||||
|
public PlayerSystem(Engine gameEngine){
|
||||||
|
this.gameEngine = gameEngine;
|
||||||
|
registrationSet = new BitSet();
|
||||||
|
registrationSet.set(gameEngine.getComponentIndex(Control.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(Entity inputEntity){
|
||||||
|
this.inputEntity = inputEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() throws Exception {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(double dt) {
|
||||||
|
int state = ((Input)gameEngine.getComponentData(inputEntity, Input.class)).input.get();
|
||||||
|
// The value of the input may change before control leaves here; sychronisation isn't
|
||||||
|
// hugely important through this section. So we can just ignore the change
|
||||||
|
for (Entity entity : entities) {
|
||||||
|
Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class);
|
||||||
|
Sprite sprite = (Sprite)gameEngine.getComponentData(entity, Sprite.class);
|
||||||
|
if (state == 0){ // W
|
||||||
|
pos.y -= sprite.height/2;
|
||||||
|
}
|
||||||
|
else if (state == 1){ // S
|
||||||
|
pos.y += sprite.height/2;
|
||||||
|
}
|
||||||
|
else if (state == 2){ // A
|
||||||
|
pos.x -= sprite.width/2;
|
||||||
|
}
|
||||||
|
else if (state == 3){ // D
|
||||||
|
pos.x += sprite.width/2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Finally, unset the state
|
||||||
|
((Input)gameEngine.getComponentData(inputEntity, Input.class)).input.set(-1); // Unset the state, it has been handled
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,19 +6,23 @@ import javafx.application.Application;
|
|||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import nz.ac.massey.javaecs.ECSSystem;
|
import nz.ac.massey.javaecs.ECSSystem;
|
||||||
import nz.ac.massey.javaecs.Engine;
|
import nz.ac.massey.javaecs.Engine;
|
||||||
import nz.ac.massey.javaecs.Entity;
|
import nz.ac.massey.javaecs.Entity;
|
||||||
import nz.ac.massey.javaecs.examples.Components.Control;
|
import nz.ac.massey.javaecs.examples.Components.Control;
|
||||||
|
import nz.ac.massey.javaecs.examples.Components.Input;
|
||||||
import nz.ac.massey.javaecs.examples.Components.Render;
|
import nz.ac.massey.javaecs.examples.Components.Render;
|
||||||
import nz.ac.massey.javaecs.examples.Components.Sprite;
|
import nz.ac.massey.javaecs.examples.Components.Sprite;
|
||||||
import nz.ac.massey.javaecs.examples.Components.Vec2D;
|
import nz.ac.massey.javaecs.examples.Components.Vec2D;
|
||||||
|
/*
|
||||||
|
* This render system is different from demo 1, as its main functionality is provided directly by the program, not as an entity.
|
||||||
|
*/
|
||||||
public class RenderSystem extends ECSSystem {
|
public class RenderSystem extends ECSSystem {
|
||||||
JFXView jFXView;
|
|
||||||
Engine gameEngine;
|
Engine gameEngine;
|
||||||
|
Group renderGroup;
|
||||||
Thread renderThread;
|
Thread renderThread;
|
||||||
double renderScale;
|
double renderScale;
|
||||||
int screenX = 1024;
|
int screenX = 1024;
|
||||||
@ -29,69 +33,43 @@ public class RenderSystem extends ECSSystem {
|
|||||||
// Set registrations
|
// Set registrations
|
||||||
registrationSet = new BitSet();
|
registrationSet = new BitSet();
|
||||||
registrationSet.set(gameEngine.getComponentIndex(Render.class));
|
registrationSet.set(gameEngine.getComponentIndex(Render.class));
|
||||||
registrationSet.set(gameEngine.getComponentIndex(Vec2D.class));
|
|
||||||
this.renderScale = renderScale;
|
this.renderScale = renderScale;
|
||||||
}
|
}
|
||||||
|
public void init(Group renderGroup) throws Exception {
|
||||||
@Override
|
this.renderGroup = renderGroup;
|
||||||
public void init() {
|
|
||||||
// Spawn a new asynchronous thread (won't rejoin the main program flow)
|
|
||||||
renderThread = new Thread(new RenderStarter());
|
|
||||||
renderThread.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void init() throws Exception {
|
||||||
Group renderScene = new Group();
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(double dt) {
|
||||||
|
Group frame = new Group();
|
||||||
for (Entity entity : entities) {
|
for (Entity entity : entities) {
|
||||||
if (((Render)gameEngine.getComponentData(entity, Render.class)).renderType == Control.class){
|
Vec2D pos = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class);
|
||||||
// Do control updates here
|
if (((Render)gameEngine.getComponentData(entity, Render.class)).renderType == Sprite.class){
|
||||||
}
|
// Render the sprite
|
||||||
else if (((Render)gameEngine.getComponentData(entity, Render.class)).renderType == Sprite.class){
|
|
||||||
Vec2D vec2d = (Vec2D)gameEngine.getComponentData(entity, Vec2D.class);
|
|
||||||
Sprite sprite = (Sprite)gameEngine.getComponentData(entity, Sprite.class);
|
Sprite sprite = (Sprite)gameEngine.getComponentData(entity, Sprite.class);
|
||||||
|
ImageView spriteRender = new ImageView(sprite.sprite);
|
||||||
|
spriteRender.setX(pos.x);
|
||||||
|
spriteRender.setY(pos.y);
|
||||||
|
spriteRender.setFitWidth(sprite.width);
|
||||||
|
spriteRender.setFitHeight(sprite.height);
|
||||||
|
frame.getChildren().add(spriteRender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Must be run by the UI thread, not the main thread.
|
// Must be run by the UI thread, not the main thread.
|
||||||
// This dispatches the operation run() to the UI.
|
// This dispatches the operation run() to the UI.
|
||||||
Platform.runLater(new Runnable(){
|
Platform.runLater(new Runnable(){
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
JFXView.root.getChildren().clear();
|
renderGroup.getChildren().clear();
|
||||||
JFXView.root.getChildren().add(renderScene);
|
renderGroup.getChildren().add(frame);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a renderer
|
|
||||||
public class RenderStarter implements Runnable{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
JFXView.run();
|
|
||||||
}
|
|
||||||
void updateScene(Group newGroup){
|
|
||||||
JFXView.root.getChildren().clear();
|
|
||||||
JFXView.root.getChildren().add(newGroup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class JFXView extends Application {
|
|
||||||
private static Group root;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start(Stage primaryStage) throws Exception {
|
|
||||||
// based on the colorful circles sample at https://docs.oracle.com/javase/8/javafx/get-started-tutorial/animation.htm
|
|
||||||
root = new Group();
|
|
||||||
Scene scene = new Scene(root, 1024, 1024, Color.BLACK);
|
|
||||||
primaryStage.setScene(scene);
|
|
||||||
primaryStage.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void run(){
|
|
||||||
launch(new String[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
BIN
demo2/src/sprite.png
Normal file
BIN
demo2/src/sprite.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Loading…
x
Reference in New Issue
Block a user