Initial Commit

This commit is contained in:
2025-07-21 12:20:41 +02:00
commit 03a60da816
49 changed files with 4542 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
eclipse.project.name = appName + '-core'
dependencies {
api "com.badlogicgames.gdx:gdx:$gdxVersion"
api "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
}
@@ -0,0 +1,92 @@
package io.doppelspalt;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
public class DoppelspaltSimulation implements Screen {
private final Main app;
private OrthographicCamera camera;
private Viewport viewport;
private ShapeRenderer shapeRenderer;
// Physikalische Parameter
private static final float WAVELENGTH = 550e-9f; // Wellenlänge in Metern
private static final float SLIT_DISTANCE = 0.0002f; // Abstand zwischen den Spalten
private static final float SLIT_WIDTH = 0.00005f; // Breite eines Spalts
private static final float SCREEN_DISTANCE = 1.0f; // Abstand zur Projektionsfläche
private final int screenPixelWidth = 1280;
private final int screenPixelHeight = 720;
public DoppelspaltSimulation(Main app) {
this.app = app;
camera = new OrthographicCamera();
viewport = new FitViewport(screenPixelWidth, screenPixelHeight, camera);
shapeRenderer = new ShapeRenderer();
}
@Override
public void show() {}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.05f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
renderInterferencePattern();
shapeRenderer.end();
}
private void renderInterferencePattern() {
float screenCenterY = screenPixelHeight / 2f;
float scale = 1e6f; // Maßstab für Umrechnung von Metern zu Pixeln
for (int x = 0; x < screenPixelWidth; x++) {
// Umrechnung der x-Position in Meter (relativ zur Mitte)
float screenX = ((float) x / screenPixelWidth - 0.5f);
float position = screenX * 0.01f; // ca. ±0.005 m auf dem Schirm
// Berechne Gangunterschied Δs = d * sin(θ) ≈ d * tan(θ) = d * y / L
float deltaS = SLIT_DISTANCE * position / SCREEN_DISTANCE;
// Interferenz: I ∝ cos²(π Δs / λ)
float intensity = (float) Math.pow(Math.cos(Math.PI * deltaS / WAVELENGTH), 2);
// Diffraction envelope (Einzelspalt)
float beta = (float) ((Math.PI * SLIT_WIDTH * position) / (WAVELENGTH * SCREEN_DISTANCE));
float envelope = beta != 0 ? (float) Math.pow(Math.sin(beta) / beta, 2) : 1f;
float totalIntensity = intensity * envelope;
// Zeichne vertikale Linie proportional zur Intensität
float lineHeight = totalIntensity * screenPixelHeight;
float y = screenCenterY - lineHeight / 2f;
shapeRenderer.setColor(totalIntensity, totalIntensity, totalIntensity, 1);
shapeRenderer.rect(x, y, 1, lineHeight);
}
}
@Override
public void resize(int width, int height) {
viewport.update(width, height, true);
}
@Override public void pause() {}
@Override public void resume() {}
@Override public void hide() {}
@Override public void dispose() {
shapeRenderer.dispose();
}
}
@@ -0,0 +1,41 @@
package io.doppelspalt;
import com.badlogic.gdx.Screen;
/** First screen of the application. Displayed after the application is created. */
public class FirstScreen implements Screen {
@Override
public void show() {
// Prepare your screen here.
}
@Override
public void render(float delta) {
// Draw your screen here. "delta" is the time since last render in seconds.
}
@Override
public void resize(int width, int height) {
// Resize your screen here. The parameters represent the new window size.
}
@Override
public void pause() {
// Invoked when your application is paused.
}
@Override
public void resume() {
// Invoked when your application is resumed after pause.
}
@Override
public void hide() {
// This method is called when another screen replaces this one.
}
@Override
public void dispose() {
// Destroy screen's assets here.
}
}
@@ -0,0 +1,210 @@
package io.doppelspalt;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
public class FullscreenButton extends ImageButton {
private ImageButton fullscreenButton;
private boolean isFullscreen;
private Stage stage;
private Skin skin;
private int FULL_BUTTON_SIZE = 50;
public FullscreenButton(Stage stage, Skin skin) {
super(skin);
this.stage = stage;
this.skin = skin;
this.isFullscreen = false;
// Statt Icons verwenden wir jetzt farbige Rechtecke aus der Skin:
ImageButton.ImageButtonStyle style = new ImageButton.ImageButtonStyle();
style.imageUp = skin.newDrawable("rect", Color.RED); // sichtbar in Rot
style.imageDown = skin.newDrawable("rect", Color.DARK_GRAY); // beim Drücken dunkelgrau
fullscreenButton = new ImageButton(style);
fullscreenButton.addListener(new TextTooltip("Toggle fullscreen", skin));
// Sichtbar positionieren:
fullscreenButton.setSize(100, 100);
fullscreenButton.setPosition(10, 10);
fullscreenButton.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
toggleFullscreen();
}
});
}
public void addToStage(Stage stage) {
stage.addActor(fullscreenButton);
}
private void toggleFullscreen() {
if (isFullscreen) {
Gdx.graphics.setWindowedMode(1920, 1080);
} else {
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
}
isFullscreen = !isFullscreen;
// Icon-Update entfällt hier, da wir keine Icons verwenden
}
public void toFront() {
fullscreenButton.toFront();
}
public void dispose() {
// keine Texturen zum Entsorgen
}
}
/*
package io.doppelspalt;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.scenes.scene2d.utils.*;
public class FullscreenButton extends Button {
private ImageButton fullscreenButton;
private boolean isFullscreen;
private Stage stage;
private Skin skin;
private Texture fullscreenIcon;
private Texture windowedIcon;
private static int FULL_BUTTON_SIZE = 50;
public FullscreenButton(Stage stage, Skin skin) {
super(skin);
this.stage = stage;
this.skin = skin;
this.isFullscreen = false;
windowedIcon = new Texture(Gdx.files.internal("windowed-1.png"));
fullscreenIcon = new Texture(Gdx.files.internal("fullscreen-1.png"));
ImageButton.ImageButtonStyle style = new ImageButton.ImageButtonStyle();
style.imageUp = new TextureRegionDrawable(new TextureRegion(fullscreenIcon));
style.imageDown = new TextureRegionDrawable(new TextureRegion(fullscreenIcon));
fullscreenButton = new ImageButton(style);
fullscreenButton.addListener(new TextTooltip("Toggle fullscreen", skin));
fullscreenButton.setSize(FULL_BUTTON_SIZE, FULL_BUTTON_SIZE);
fullscreenButton.setPosition(0, 0);
fullscreenButton.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
toggleFullscreen();
}
});
}
public void addToStage(Stage stage) {
stage.addActor(fullscreenButton);
}
private void toggleFullscreen() {
if (isFullscreen) {
Gdx.graphics.setWindowedMode(1920, 1080);
} else {
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
}
isFullscreen = !isFullscreen;
updateButtonIcon();
}
private void updateButtonIcon() {
Texture newTexture = isFullscreen ? windowedIcon : fullscreenIcon;
((TextureRegionDrawable) fullscreenButton.getStyle().imageUp).setRegion(new TextureRegion(newTexture));
}
public void dispose() {
fullscreenIcon.dispose();
windowedIcon.dispose();
}
}
public class FullscreenButton extends ImageButton {
private boolean isFullscreen;
private Texture fullscreenIcon;
private Texture windowedIcon;
private static final int FULL_BUTTON_SIZE = 50;
public FullscreenButton(Stage stage, Skin skin) {
super(createStyle(skin));
this.isFullscreen = false;
windowedIcon = new Texture(Gdx.files.internal("windowed-1.png"));
fullscreenIcon = new Texture(Gdx.files.internal("fullscreen-1.png"));
setSize(FULL_BUTTON_SIZE, FULL_BUTTON_SIZE);
addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
toggleFullscreen();
}
});
}
private static ImageButtonStyle createStyle(Skin skin) {
Texture fullscreenIcon = new Texture(Gdx.files.internal("fullscreen-1.png"));
ImageButtonStyle style = new ImageButtonStyle();
style.imageUp = new TextureRegionDrawable(new TextureRegion(fullscreenIcon));
style.imageDown = new TextureRegionDrawable(new TextureRegion(fullscreenIcon));
return style;
}
private void toggleFullscreen() {
if (isFullscreen) {
Gdx.graphics.setWindowedMode(1920, 1080);
} else {
Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode());
}
isFullscreen = !isFullscreen;
updateButtonIcon();
}
private void updateButtonIcon() {
Texture newTexture = isFullscreen ? windowedIcon : fullscreenIcon;
((TextureRegionDrawable)getStyle().imageUp).setRegion(new TextureRegion(newTexture));
((TextureRegionDrawable)getStyle().imageDown).setRegion(new TextureRegion(newTexture));
}
public void addToStage(Stage stage) {
stage.addActor(this);
}
public void dispose() {
fullscreenIcon.dispose();
windowedIcon.dispose();
}
}
*/
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.10.0//EN" "https://www.gwtproject.org/doctype/2.10.0/gwt-module.dtd">
<module>
<source path="" />
</module>
+445
View File
@@ -0,0 +1,445 @@
package io.doppelspalt;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
public class Main implements ApplicationListener {
private Viewport viewport;
private OrthographicCamera camera;
private ShapeRenderer shapeRenderer;
private BitmapFont font;
private Stage stage;
private Skin skin;
private Table table;
private int lambda = 50;
private int gitterD = 75;
private int winkel = 90;
private Label fpsLabel;
private Slider lambdaSlider, dSlider, winkelSlider;
private Label ratioLabel;
private FullscreenButton fullButton;
@Override
public void create() {
font = new BitmapFont(Gdx.files.internal("bitmap/c059.fnt"));
camera = new OrthographicCamera();
table = new Table();
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
shapeRenderer = new ShapeRenderer();
//viewport = new FitViewport(1920, 1080, camera);
viewport = new ScreenViewport();
stage = new Stage(viewport);
Gdx.input.setInputProcessor(stage);
skin = new Skin(Gdx.files.internal("ui/uiskin.json"));
fullButton = new FullscreenButton(stage, skin);
setupUI();
}
private void setupUI() {
lambdaSlider = new Slider(10, 85, 1, false, skin);
dSlider = new Slider(0, 150, 1, false, skin);
winkelSlider = new Slider(0, 180, 1, false, skin);
lambdaSlider.setValue(lambda);
dSlider.setValue(gitterD);
winkelSlider.setValue(winkel);
Label.LabelStyle style = new Label.LabelStyle(skin.getFont("font"), Color.BLACK);
style.font = font;
ratioLabel = new Label("d/lambda = " + formatRatio(), style);
lambdaSlider.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
lambda = (int) lambdaSlider.getValue();
updateRatio();
}
});
dSlider.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
gitterD = (int) dSlider.getValue();
updateRatio();
}
});
winkelSlider.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
winkel = (int) winkelSlider.getValue();
}
});
table.top().left();
table.pack();
table.setPosition(10, viewport.getWorldHeight() - 10);
if (viewport.getWorldHeight() > viewport.getWorldWidth()) {
table.setWidth(viewport.getWorldWidth() - 20);
}
fpsLabel = new Label("FPS: 0", style);
//table.row();
//table.add(fpsLabel).left().colspan(2).padTop(10);
//table.row();
Label lambdaLabel = new Label("Lambda", style);
table.add(lambdaLabel).left().pad(5);
table.add(lambdaSlider).width(300).pad(5);
table.row();
//Label dLabel = new Label("Slit distance d", style);
Label dLabel = new Label("D", style);
table.add(dLabel).left().pad(5);
table.add(dSlider).width(300).pad(5);
table.row();
//Label winkelLabel = new Label("Angle of incidence", style);
Label winkelLabel = new Label("Winkel", style);
table.add(winkelLabel).left().pad(5);
table.add(winkelSlider).width(300).pad(5);
table.row();
table.add(ratioLabel).colspan(2).padTop(10);
table.row();
TextButton resetButton = new TextButton("Reset", skin);
resetButton.setSize(10, 10);
resetButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
lambdaSlider.setValue(50);
dSlider.setValue(75);
winkelSlider.setValue(90);
lambda = 50;
gitterD = 75;
winkel = 90;
updateRatio();
}
});
table.add(resetButton)
.colspan(2)
.padTop(10)
.width(100)
.height(30);
table.row();
stage.addActor(table);
//stage.setDebugAll(true);
//fullButton.addToStage(stage);
//fullButton.toFront();
}
private void updateRatio() {
ratioLabel.setText("d/lambda = " + formatRatio());
}
private String formatRatio() {
double value = (double) gitterD / lambda;
return formatDouble(value, 2);
}
private String formatDouble(double value, int decimals) {
double scale = Math.pow(10, decimals);
return String.valueOf(Math.round(value * scale) / scale);
}
@Override
public void render() {
float delta = Gdx.graphics.getDeltaTime();
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
fpsLabel.setText("FPS: " + Gdx.graphics.getFramesPerSecond());
camera.update();
shapeRenderer.setProjectionMatrix(camera.combined);
drawInterference();
stage.act(delta);
stage.draw();
}
private void drawInterference() {
int width = Gdx.graphics.getWidth();
int height = Gdx.graphics.getHeight();
int xSpalt = width / 3;
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
int y1 = (height - gitterD) / 2;
int y2 = (height + gitterD) / 2;
drawCircularWaves(xSpalt, y1, width, height);
drawCircularWaves(xSpalt, y2, width, height);
shapeRenderer.end();
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
drawBackgroundForSinus(xSpalt, height);
drawWallWithSlits(xSpalt, height);
shapeRenderer.setColor(Color.RED);
drawIntersectionPoints(xSpalt, width, height);
shapeRenderer.end();
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
drawSinusWave(xSpalt, height);
drawIncidentWave(xSpalt, height);
shapeRenderer.end();
}
private void drawSinusWave(int breite, int hoehe) {
double phi = Math.toRadians(winkel - 90);
double amplitude = hoehe / 12.0;
int lSinus;
if (Math.abs(phi) < Math.atan(0.5 * hoehe / (double) breite)) {
lSinus = (int) (breite / Math.cos(phi));
} else {
lSinus = (int) (0.5 * hoehe / Math.abs(Math.sin(phi)));
}
float[] points = new float[(lSinus - 1) * 4];
for (int i = 0; i < lSinus - 1; i++) {
double x0 = (i - lSinus);
double y0 = amplitude * Math.sin(1.5 * Math.PI + 2 * Math.PI * ((i - lSinus) % lambda) / lambda);
double x1 = (i + 1 - lSinus);
double y1 = amplitude * Math.sin(1.5 * Math.PI + 2 * Math.PI * ((i + 1 - lSinus) % lambda) / lambda);
float xStart = (float) (x0 * Math.cos(phi) + y0 * Math.sin(phi)) + breite;
float yStart = (float) (-x0 * Math.sin(phi) + y0 * Math.cos(phi)) + hoehe / 2f;
float xEnd = (float) (x1 * Math.cos(phi) + y1 * Math.sin(phi)) + breite;
float yEnd = (float) (-x1 * Math.sin(phi) + y1 * Math.cos(phi)) + hoehe / 2f;
int idx = i * 4;
points[idx] = xStart;
points[idx + 1] = yStart;
points[idx + 2] = xEnd;
points[idx + 3] = yEnd;
}
shapeRenderer.setColor(Color.RED);
for (int i = 0; i < points.length; i += 4) {
shapeRenderer.line(points[i], points[i + 1], points[i + 2], points[i + 3]);
}
}
private void drawWallWithSlits(int xSpalt, int height) {
int loch = 5;
int ySpalt1 = (height - gitterD) / 2;
int ySpalt2 = (height + gitterD) / 2;
int balkenBreite = 5;
shapeRenderer.setColor(Color.BLACK);
shapeRenderer.rect(xSpalt - 2, 0, balkenBreite, ySpalt1 - loch);
shapeRenderer.rect(xSpalt - 2, ySpalt1 + loch, balkenBreite, gitterD - 2 * loch);
shapeRenderer.rect(xSpalt - 2, ySpalt2 + loch, balkenBreite, height - ySpalt2 - loch);
}
private void drawBackgroundForSinus(int xSpalt, int height) {
shapeRenderer.setColor(Color.WHITE);
shapeRenderer.rect(0, 0, xSpalt - 5, height);
}
private void drawIncidentWave(int xSpalt, int height) {
shapeRenderer.setColor(Color.BLACK);
double phi = Math.toRadians(winkel);
double sinPhi = Math.sin(phi);
double cosPhi = Math.cos(phi);
if (winkel == 90) {
for (int i = xSpalt; i > 0; i -= lambda) {
shapeRenderer.line(i, 0, i, height);
}
} else if (winkel == 0 || winkel == 180) {
for (int i = (height / 2) % lambda; i <= height; i += lambda) {
shapeRenderer.line(0, i, xSpalt, i);
}
} else {
double dMin, dMax, d0;
if (winkel < 90) {
dMin = 0.0;
double d1 = xSpalt * sinPhi + (height / 2.0) * cosPhi;
dMax = xSpalt * sinPhi + height * cosPhi;
d0 = dMin + (d1 - dMin) % lambda;
} else {
dMin = height * cosPhi;
double d1 = xSpalt * sinPhi + (height / 2.0) * cosPhi;
dMax = xSpalt * sinPhi;
d0 = dMin + (d1 - dMin) % lambda;
}
for (double d = d0; d < dMax; d += lambda) {
double schnittY_Achse = d / sinPhi;
double schnittX_Achse = d / cosPhi;
double schnittX_breite = (d - xSpalt * sinPhi) / cosPhi;
double schnittY_hoehe = (d - height * cosPhi) / sinPhi;
int x0, y0, x1, y1;
if (schnittY_Achse < 0.0) {
x0 = 0;
y0 = (int) schnittX_Achse;
} else if (schnittY_Achse < xSpalt) {
x0 = (int) schnittY_Achse;
y0 = 0;
} else {
x0 = xSpalt;
y0 = (int) schnittX_breite;
}
if (schnittY_hoehe < 0.0) {
x1 = 0;
y1 = (int) schnittX_Achse;
} else if (schnittY_hoehe < xSpalt) {
x1 = (int) schnittY_hoehe;
y1 = height;
} else {
x1 = xSpalt;
y1 = (int) schnittX_breite;
}
shapeRenderer.line(x0, y0, x1, y1);
}
}
}
private void drawCircularWaves(int x, int y, int width, int height) {
shapeRenderer.setColor(Color.BLACK);
double phi = Math.toRadians(winkel - 90);
int s0;
if (y > height / 2) {
s0 = (int) ((gitterD / 2.0) * Math.sin(phi)) % lambda;
} else {
s0 = -(int) ((gitterD / 2.0) * Math.sin(phi)) % lambda;
}
if (s0 < 0) s0 += lambda;
for (int i = 0; i * lambda + s0 < Math.max(width, height) * 2; i++) {
int r = i * lambda + s0;
if (r > 0) {
shapeRenderer.circle(x, y, r, 64);
}
}
}
private void drawIntersectionPoints(int x, int width, int height) {
double phi = Math.toRadians(winkel - 90);
double s0 = (gitterD / 2.0) * Math.sin(phi) % lambda;
int n = (int)(Math.max(width, height) * 1.5 / lambda);
int radius = 12;
if (lambda <= 20) radius = 9;
if (lambda <= 15) radius = 7;
if (radius < 5) radius = 5;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
double r1 = i * lambda - s0;
double r2 = j * lambda + s0;
if (r1 + r2 > gitterD && r1 <= r2 + gitterD && r2 <= r1 + gitterD) {
if (gitterD != 0) {
double y = (r1 * r1 - r2 * r2 + gitterD * gitterD) / (2.0 * gitterD);
double xRel = Math.sqrt(Math.abs(r1 * r1 - y * y));
float drawX = (float) (x + xRel);
float drawY = (float) ((height - gitterD) / 2.0 + y);
if (drawY >= 0 && drawY <= height) {
shapeRenderer.circle(drawX, drawY, radius);
}
}
}
}
}
}
@Override
public void resize(int width, int height) {
viewport.update(width, height, true);
table.setPosition(10, viewport.getWorldHeight() - 10);
camera.setToOrtho(false, width, height);
}
@Override
public void dispose() {
stage.dispose();
shapeRenderer.dispose();
skin.dispose();
}
@Override public void pause() {}
@Override public void resume() {}
}