Initial commit
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
sourceCompatibility = 1.7
|
||||
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
|
||||
|
||||
sourceSets.main.java.srcDirs = [ "src/" ]
|
||||
|
||||
eclipse.project.name = appName + "-core"
|
||||
dependencies {
|
||||
// Основное ядро LibGDX
|
||||
api "com.badlogicgames.gdx:gdx:$gdxVersion"
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.audio.Music;
|
||||
|
||||
public class AudioManager {
|
||||
public boolean isMusicOn = true;
|
||||
public static final String BACKGROUND_MUSIC_PATH = "bg.mp3";
|
||||
public Music backgroundMusic;
|
||||
|
||||
public AudioManager() {
|
||||
backgroundMusic = Gdx.audio.newMusic(Gdx.files.internal(BACKGROUND_MUSIC_PATH));
|
||||
backgroundMusic.setVolume(1f);
|
||||
backgroundMusic.setLooping(true);
|
||||
updateSoundFlag();
|
||||
updateMusicFlag();
|
||||
}
|
||||
|
||||
private void updateSoundFlag() {
|
||||
}
|
||||
|
||||
public void updateMusicFlag() {
|
||||
if (isMusicOn) backgroundMusic.play();
|
||||
else backgroundMusic.stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.graphics.g3d.Model;
|
||||
import com.badlogic.gdx.graphics.g3d.ModelInstance;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
|
||||
class Emitter {
|
||||
public ModelInstance instance;
|
||||
public Vector3 direction;
|
||||
|
||||
public Emitter(Model m, float x, float y, float z, float dx, float dy, float dz) {
|
||||
instance = new ModelInstance(m, x, y, z);
|
||||
direction = new Vector3(dx, dy, dz).nor();
|
||||
instance.transform.setToLookAt(direction, Vector3.Y).inv().setTranslation(x, y, z);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.*;
|
||||
import com.badlogic.gdx.graphics.*;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||
import com.badlogic.gdx.graphics.g3d.*;
|
||||
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
|
||||
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
|
||||
import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
|
||||
import com.badlogic.gdx.math.*;
|
||||
import com.badlogic.gdx.scenes.scene2d.*;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.*;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||
import com.badlogic.gdx.utils.viewport.ScreenViewport;
|
||||
|
||||
public class GameScreen implements Screen {
|
||||
private final MyGdxGame game;
|
||||
private PerspectiveCamera cam;
|
||||
private CameraInputController camCtrl;
|
||||
private Environment env;
|
||||
private SceneManager sm;
|
||||
private LaserRenderer lr;
|
||||
private float winTimer = 0;
|
||||
private float levelTime = 0; // Общее время прохождения уровня
|
||||
private final int level;
|
||||
private Stage stage;
|
||||
private Texture uiBtnTexture;
|
||||
private BitmapFont font;
|
||||
private HelpUI helpUI;
|
||||
private Label timerLabel; // Визуальный элемент таймера
|
||||
|
||||
public GameScreen(MyGdxGame game, int level) {
|
||||
this.game = game;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
cam.position.set(50, 60, 50);
|
||||
cam.lookAt(0, 0, 0);
|
||||
cam.near = 10f;
|
||||
cam.far = 500f;
|
||||
cam.update();
|
||||
camCtrl = new CameraInputController(cam);
|
||||
|
||||
camCtrl.pinchZoomFactor = 50f;
|
||||
camCtrl.scrollFactor = -0.5f;
|
||||
|
||||
stage = new Stage(new ScreenViewport());
|
||||
Gdx.input.setInputProcessor(new InputMultiplexer(stage, camCtrl));
|
||||
|
||||
/* font = new BitmapFont();
|
||||
font.getData().setScale(2f);
|
||||
*/
|
||||
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("Montserrat-Bold.ttf"));
|
||||
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
|
||||
|
||||
// 2. Устанавливаем нужный размер СРАЗУ (вместо setScale)
|
||||
parameter.size = 20;
|
||||
|
||||
// 3. Указываем, какие символы нужно подготовить (обязательно добавляем русские!)
|
||||
String RUSSIAN_CHARACTERS = "абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
|
||||
parameter.characters = FreeTypeFontGenerator.DEFAULT_CHARS + RUSSIAN_CHARACTERS;
|
||||
|
||||
// 4. Генерируем сам шрифт
|
||||
font = generator.generateFont(parameter);
|
||||
|
||||
|
||||
|
||||
uiBtnTexture = createButtonTexture();
|
||||
createMenuButton();
|
||||
createTimerUI(); // Создаем интерфейс таймера
|
||||
|
||||
helpUI = new HelpUI(stage, font, game);
|
||||
|
||||
env = new Environment();
|
||||
env.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
|
||||
env.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
|
||||
|
||||
sm = new SceneManager();
|
||||
sm.loadLevel(level);
|
||||
lr = new LaserRenderer(game.shapeRenderer);
|
||||
|
||||
levelTime = 0; // Сброс таймера при старте
|
||||
}
|
||||
|
||||
private void createTimerUI() {
|
||||
timerLabel = new Label("ВРЕМЯ: 0.0", new Label.LabelStyle(font, Color.WHITE));
|
||||
timerLabel.setPosition(20, Gdx.graphics.getHeight() - 150);
|
||||
stage.addActor(timerLabel);
|
||||
}
|
||||
|
||||
private void createMenuButton() {
|
||||
Stack menuStack = new Stack();
|
||||
Image btnImg = new Image(uiBtnTexture);
|
||||
Label btnLbl = new Label("МЕНЮ", new Label.LabelStyle(font, Color.BLACK));
|
||||
btnLbl.setAlignment(com.badlogic.gdx.utils.Align.center);
|
||||
|
||||
menuStack.add(btnImg);
|
||||
menuStack.add(btnLbl);
|
||||
menuStack.setSize(140, 70);
|
||||
menuStack.setPosition(20, Gdx.graphics.getHeight() - 90);
|
||||
|
||||
menuStack.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
game.setScreen(new LevelSelectScreen(game));
|
||||
}
|
||||
});
|
||||
stage.addActor(menuStack);
|
||||
}
|
||||
|
||||
private Texture createButtonTexture() {
|
||||
Pixmap pm = new Pixmap(128, 64, Pixmap.Format.RGBA8888);
|
||||
pm.setColor(Color.BLACK);
|
||||
pm.fillRectangle(0, 0, 128, 64);
|
||||
pm.setColor(Color.WHITE);
|
||||
pm.fillRectangle(3, 3, 122, 58);
|
||||
Texture t = new Texture(pm);
|
||||
pm.dispose();
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
// Обновляем таймер, только если уровень еще не пройден полностью (до начала winTimer)
|
||||
boolean allHit = sm.targets.size > 0;
|
||||
for (Target t : sm.targets) {
|
||||
if (!t.hit) {
|
||||
allHit = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allHit) {
|
||||
levelTime += delta;
|
||||
timerLabel.setText(String.format("ВРЕМЯ: %.1f", levelTime));
|
||||
|
||||
// Подсветка таймера золотым, если укладываемся в лимит
|
||||
float timeLimit = 2.0f + (0.1f * level);
|
||||
if (levelTime <= timeLimit) {
|
||||
timerLabel.setColor(Color.GOLD);
|
||||
} else {
|
||||
timerLabel.setColor(Color.GRAY);
|
||||
}
|
||||
}
|
||||
|
||||
if (Gdx.input.justTouched()) {
|
||||
boolean hitUI = stage.hit(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY(), true) != null;
|
||||
if (!hitUI) {
|
||||
sm.checkClick(cam.getPickRay(Gdx.input.getX(), Gdx.input.getY()));
|
||||
}
|
||||
}
|
||||
|
||||
camCtrl.update();
|
||||
lr.calculate(sm);
|
||||
|
||||
if (allHit) {
|
||||
winTimer += delta;
|
||||
if (winTimer > 2f) {
|
||||
Preferences prefs = Gdx.app.getPreferences("LaserPuzzleSettings");
|
||||
int reachedLevel = prefs.getInteger("reachedLevel", 1);
|
||||
|
||||
// Сохраняем прогресс уровней
|
||||
if (level >= reachedLevel) {
|
||||
prefs.putInteger("reachedLevel", level + 1);
|
||||
}
|
||||
|
||||
// Проверяем на "золотую звезду" (лимит времени)
|
||||
float timeLimit = 2.0f + (0.1f * level);
|
||||
if (levelTime <= timeLimit) {
|
||||
// Сохраняем флаг золотого уровня
|
||||
prefs.putBoolean("gold_" + level, true);
|
||||
}
|
||||
|
||||
prefs.flush();
|
||||
|
||||
// Переход на следующий уровень
|
||||
if (level < 40) {
|
||||
game.setScreen(new GameScreen(game, level + 1));
|
||||
} else {
|
||||
game.setScreen(new LevelSelectScreen(game));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
winTimer = 0;
|
||||
}
|
||||
|
||||
Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
game.modelBatch.begin(cam);
|
||||
sm.render(game.modelBatch, env);
|
||||
game.modelBatch.end();
|
||||
|
||||
lr.render(cam);
|
||||
|
||||
stage.act(delta);
|
||||
stage.draw();
|
||||
}
|
||||
|
||||
@Override public void resize(int width, int height) {
|
||||
stage.getViewport().update(width, height, true);
|
||||
timerLabel.setPosition(100, height - 150);
|
||||
}
|
||||
|
||||
@Override public void dispose() {
|
||||
if (sm != null) sm.dispose();
|
||||
if (stage != null) stage.dispose();
|
||||
if (uiBtnTexture != null) uiBtnTexture.dispose();
|
||||
if (font != null) font.dispose();
|
||||
if (helpUI != null) helpUI.dispose();
|
||||
}
|
||||
@Override public void pause() {}
|
||||
@Override public void resume() {}
|
||||
@Override public void hide() {}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
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.utils.Align;
|
||||
|
||||
public class HelpUI {
|
||||
private final Stage stage;
|
||||
private final Table helpMenu;
|
||||
private Texture circleTexture;
|
||||
private Texture rectTexture;
|
||||
private Texture closeTexture;
|
||||
private final Label musicStatusLabel;
|
||||
|
||||
public HelpUI(final Stage stage, BitmapFont font, final MyGdxGame game) {
|
||||
this.stage = stage;
|
||||
circleTexture = createCircleTexture(60, Color.WHITE);
|
||||
rectTexture = createRectTexture(1, 1, new Color(0, 0, 0, 0.85f));
|
||||
closeTexture = createRectTexture(40, 40, Color.RED);
|
||||
|
||||
float screenWidth = stage.getViewport().getWorldWidth();
|
||||
float screenHeight = stage.getViewport().getWorldHeight();
|
||||
|
||||
// --- Кнопка Помощи (?) ---
|
||||
Stack helpBtn = new Stack();
|
||||
Image bgHelp = new Image(circleTexture);
|
||||
Label symbolHelp = new Label("?", new Label.LabelStyle(font, Color.BLACK));
|
||||
symbolHelp.setAlignment(Align.center);
|
||||
|
||||
helpBtn.add(bgHelp);
|
||||
helpBtn.add(symbolHelp);
|
||||
helpBtn.setSize(60, 60);
|
||||
helpBtn.setPosition(screenWidth - 80, screenHeight - 80);
|
||||
|
||||
// --- Кнопка Музыки ---
|
||||
Stack musicBtn = new Stack();
|
||||
Image bgMusic = new Image(circleTexture);
|
||||
musicStatusLabel = new Label(game.audioManager.isMusicOn ? "ON" : "OFF", new Label.LabelStyle(font, Color.BLACK));
|
||||
musicStatusLabel.setFontScale(0.6f);
|
||||
musicStatusLabel.setAlignment(Align.center);
|
||||
|
||||
musicBtn.add(bgMusic);
|
||||
musicBtn.add(musicStatusLabel);
|
||||
musicBtn.setSize(60, 60);
|
||||
musicBtn.setPosition(screenWidth - 150, screenHeight - 80);
|
||||
|
||||
// --- Окно помощи ---
|
||||
helpMenu = new Table();
|
||||
helpMenu.setFillParent(true);
|
||||
helpMenu.setVisible(false);
|
||||
|
||||
Image overlay = new Image(rectTexture);
|
||||
overlay.setFillParent(true);
|
||||
|
||||
Table content = new Table();
|
||||
// Устанавливаем темно-синий фон для контента
|
||||
content.setBackground(new Image(createRectTexture(1, 1, new Color(0.1f, 0.1f, 0.15f, 1f))).getDrawable());
|
||||
content.pad(50); // Увеличены отступы
|
||||
|
||||
Stack closeBtn = new Stack();
|
||||
Image closeBg = new Image(closeTexture);
|
||||
Label closeX = new Label("X", new Label.LabelStyle(font, Color.WHITE));
|
||||
closeX.setAlignment(Align.center);
|
||||
closeBtn.add(closeBg);
|
||||
closeBtn.add(closeX);
|
||||
|
||||
Label title = new Label("КАК ИГРАТЬ", new Label.LabelStyle(font, Color.GOLD));
|
||||
title.setFontScale(1.2f); // Увеличен заголовок
|
||||
|
||||
// Текст с правилами
|
||||
Label description = new Label(
|
||||
"1. Нажимай на зеркала, чтобы вращать их.\n\n" +
|
||||
"2. Направляй лазер на все пирамиды-цели.\n\n" +
|
||||
"3. Когда все цели станут зелеными, уровень пройден!\n\n\n" +
|
||||
"[ СИСТЕМА ЗВЕЗД ]\n\n" +
|
||||
"Пройди уровень быстро, чтобы получить Золотой Статус.\n" +
|
||||
"Лимит времени = 2.0 сек + 0.1 сек за каждый уровень.\n" +
|
||||
"Золотые уровни подсвечиваются желтым в меню!",
|
||||
new Label.LabelStyle(font, Color.WHITE)
|
||||
);
|
||||
description.setWrap(true);
|
||||
description.setAlignment(Align.left);
|
||||
description.setFontScale(0.95f); // Масштаб текста возвращен к комфортному размеру
|
||||
|
||||
Table header = new Table();
|
||||
header.add(title).expandX().left();
|
||||
header.add(closeBtn).size(50, 50).right(); // Кнопка закрытия чуть больше
|
||||
|
||||
content.add(header).fillX().row();
|
||||
content.add(new Label("", new Label.LabelStyle(font, Color.WHITE))).pad(15).row();
|
||||
// Увеличена ширина текстового блока до 600 пикселей
|
||||
content.add(description).width(600).padTop(10);
|
||||
|
||||
helpMenu.stack(overlay, content).center();
|
||||
|
||||
// --- Слушатели ---
|
||||
helpBtn.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
helpMenu.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
closeBtn.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
helpMenu.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
musicBtn.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
game.audioManager.isMusicOn = !game.audioManager.isMusicOn;
|
||||
game.audioManager.updateMusicFlag();
|
||||
musicStatusLabel.setText(game.audioManager.isMusicOn ? "ON" : "OFF");
|
||||
}
|
||||
});
|
||||
|
||||
stage.addActor(helpBtn);
|
||||
stage.addActor(musicBtn);
|
||||
stage.addActor(helpMenu);
|
||||
}
|
||||
|
||||
private Texture createCircleTexture(int size, Color color) {
|
||||
Pixmap pixmap = new Pixmap(size, size, Pixmap.Format.RGBA8888);
|
||||
pixmap.setColor(Color.BLACK);
|
||||
pixmap.fillCircle(size / 2, size / 2, size / 2 - 1);
|
||||
pixmap.setColor(color);
|
||||
pixmap.fillCircle(size / 2, size / 2, size / 2 - 4);
|
||||
Texture t = new Texture(pixmap);
|
||||
pixmap.dispose();
|
||||
return t;
|
||||
}
|
||||
|
||||
private Texture createRectTexture(int w, int h, Color color) {
|
||||
Pixmap pixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888);
|
||||
pixmap.setColor(color);
|
||||
pixmap.fill();
|
||||
Texture t = new Texture(pixmap);
|
||||
pixmap.dispose();
|
||||
return t;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (circleTexture != null) circleTexture.dispose();
|
||||
if (rectTexture != null) rectTexture.dispose();
|
||||
if (closeTexture != null) closeTexture.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.*;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.math.*;
|
||||
import com.badlogic.gdx.math.collision.Ray;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
public class LaserRenderer {
|
||||
private final ShapeRenderer sr;
|
||||
private final Array<Array<Vector3>> paths = new Array<>();
|
||||
private final Vector3 tmpHit = new Vector3(), hitPoint = new Vector3(), normal = new Vector3();
|
||||
private final Ray ray = new Ray();
|
||||
|
||||
public LaserRenderer(ShapeRenderer sr) { this.sr = sr; }
|
||||
|
||||
public void calculate(SceneManager sm) {
|
||||
paths.clear();
|
||||
for (Target t : sm.targets) t.hit = false;
|
||||
for (Emitter e : sm.emitters) {
|
||||
Array<Vector3> path = new Array<>();
|
||||
Vector3 pos = e.instance.transform.getTranslation(new Vector3()).add(0, SceneManager.LASER_HEIGHT, 0);
|
||||
Vector3 dir = new Vector3(e.direction).nor();
|
||||
path.add(new Vector3(pos));
|
||||
trace(pos, dir, path, sm);
|
||||
paths.add(path);
|
||||
}
|
||||
}
|
||||
|
||||
private void trace(Vector3 pos, Vector3 dir, Array<Vector3> path, SceneManager sm) {
|
||||
for (int i = 0; i < 25; i++) {
|
||||
float minD = Float.MAX_VALUE;
|
||||
Object hitObj = null;
|
||||
ray.set(pos, dir);
|
||||
|
||||
for (Wall w : sm.walls) if (w.active && intersect(ray, w.instance.transform, tmpHit)) {
|
||||
float d = pos.dst2(tmpHit);
|
||||
if (d < minD) { minD = d; hitPoint.set(tmpHit); hitObj = w; }
|
||||
}
|
||||
for (Mirror m : sm.mirrors) if (intersect(ray, m.transform, tmpHit)) {
|
||||
float d = pos.dst2(tmpHit);
|
||||
if (d < minD) {
|
||||
minD = d;
|
||||
hitPoint.set(tmpHit);
|
||||
hitObj = m;
|
||||
normal.set(0, 0, 1).rot(m.transform).nor();
|
||||
}
|
||||
}
|
||||
for (Target t : sm.targets) if (Intersector.intersectRaySphere(ray, t.getPos(), 3.5f, tmpHit)) {
|
||||
float d = pos.dst2(tmpHit);
|
||||
if (d < minD) { minD = d; hitPoint.set(tmpHit); hitObj = t; }
|
||||
}
|
||||
|
||||
if (hitObj == null) {
|
||||
path.add(new Vector3(pos).add(new Vector3(dir).scl(1000f)));
|
||||
break;
|
||||
}
|
||||
|
||||
path.add(new Vector3(hitPoint));
|
||||
|
||||
if (hitObj instanceof Target) {
|
||||
((Target)hitObj).hit = true;
|
||||
break;
|
||||
}
|
||||
if (hitObj instanceof Wall) break;
|
||||
|
||||
float dot = dir.dot(normal);
|
||||
dir.sub(new Vector3(normal).scl(2 * dot)).nor();
|
||||
pos.set(hitPoint).add(new Vector3(dir).scl(0.5f));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean intersect(Ray r, Matrix4 transform, Vector3 out) {
|
||||
Matrix4 inv = new Matrix4(transform).inv();
|
||||
Ray localRay = new Ray(new Vector3(r.origin).mul(inv), new Vector3(r.direction).rot(inv));
|
||||
if (Intersector.intersectRayBounds(localRay, Mirror.bounds, out)) {
|
||||
out.mul(transform);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void render(PerspectiveCamera cam) {
|
||||
sr.setProjectionMatrix(cam.combined);
|
||||
sr.begin(ShapeRenderer.ShapeType.Line);
|
||||
Gdx.gl.glLineWidth(5);
|
||||
sr.setColor(Color.RED);
|
||||
for (Array<Vector3> p : paths) {
|
||||
for (int i = 0; i < p.size - 1; i++) {
|
||||
sr.line(p.get(i), p.get(i + 1));
|
||||
}
|
||||
}
|
||||
sr.end();
|
||||
Gdx.gl.glLineWidth(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Preferences;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||
import com.badlogic.gdx.scenes.scene2d.Stage;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
||||
import com.badlogic.gdx.utils.viewport.ScreenViewport;
|
||||
|
||||
public class LevelSelectScreen implements Screen {
|
||||
private final MyGdxGame game;
|
||||
private Stage stage;
|
||||
private BitmapFont font;
|
||||
private Texture btnTex;
|
||||
private Texture btnLockedTex;
|
||||
private Texture btnGoldTex; // Текстура для золотого уровня
|
||||
|
||||
public LevelSelectScreen(MyGdxGame game) {
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
stage = new Stage(new ScreenViewport());
|
||||
Gdx.input.setInputProcessor(stage);
|
||||
|
||||
// ВМЕСТО ЭТИХ ДВУХ СТРОК:
|
||||
/*
|
||||
font = new BitmapFont();
|
||||
font.getData().setScale(2f);
|
||||
*/
|
||||
|
||||
// 1. Создаем генератор из нашего .ttf файла
|
||||
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("Montserrat-Bold.ttf"));
|
||||
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
|
||||
|
||||
// 2. Устанавливаем нужный размер СРАЗУ (вместо setScale)
|
||||
parameter.size = 20;
|
||||
|
||||
// 3. Указываем, какие символы нужно подготовить (обязательно добавляем русские!)
|
||||
String RUSSIAN_CHARACTERS = "абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
|
||||
parameter.characters = FreeTypeFontGenerator.DEFAULT_CHARS + RUSSIAN_CHARACTERS;
|
||||
|
||||
// 4. Генерируем сам шрифт
|
||||
font = generator.generateFont(parameter);
|
||||
|
||||
|
||||
|
||||
btnTex = createBtnTexture(Color.WHITE);
|
||||
btnLockedTex = createBtnTexture(Color.GRAY);
|
||||
btnGoldTex = createBtnTexture(Color.GOLD); // Создаем золотую текстуру
|
||||
|
||||
Table container = new Table();
|
||||
container.setFillParent(true);
|
||||
|
||||
Table grid = new Table();
|
||||
grid.pad(20);
|
||||
|
||||
Preferences prefs = Gdx.app.getPreferences("LaserPuzzleSettings");
|
||||
int reachedLevel = prefs.getInteger("reachedLevel", 1);
|
||||
|
||||
for (int i = 1; i <= 40; i++) {
|
||||
final int levelNum = i;
|
||||
boolean isGold = prefs.getBoolean("gold_" + i, false); // Проверка на золото
|
||||
|
||||
TextButton.TextButtonStyle style = new TextButton.TextButtonStyle();
|
||||
style.font = font;
|
||||
|
||||
if (i <= reachedLevel) {
|
||||
// Если уровень пройден быстро, ставим золотую текстуру
|
||||
style.up = new TextureRegionDrawable(isGold ? btnGoldTex : btnTex);
|
||||
style.fontColor = Color.BLACK;
|
||||
} else {
|
||||
style.up = new TextureRegionDrawable(btnLockedTex);
|
||||
style.fontColor = Color.DARK_GRAY;
|
||||
}
|
||||
|
||||
TextButton btn = new TextButton(String.valueOf(i), style);
|
||||
|
||||
if (i <= reachedLevel) {
|
||||
btn.addListener(new ClickListener() {
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
game.setScreen(new GameScreen(game, levelNum));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
grid.add(btn).size(120, 120).pad(10);
|
||||
if (i % 5 == 0) grid.row();
|
||||
}
|
||||
|
||||
ScrollPane scroll = new ScrollPane(grid);
|
||||
container.add(new Label("ВЫБОР УРОВНЯ", new Label.LabelStyle(font, Color.WHITE))).padBottom(20).row();
|
||||
container.add(scroll).expand().fill();
|
||||
|
||||
stage.addActor(container);
|
||||
}
|
||||
|
||||
private Texture createBtnTexture(Color color) {
|
||||
Pixmap pm = new Pixmap(128, 128, Pixmap.Format.RGBA8888);
|
||||
pm.setColor(Color.BLACK);
|
||||
pm.fillRectangle(0, 0, 128, 128);
|
||||
pm.setColor(color);
|
||||
pm.fillRectangle(4, 4, 120, 120);
|
||||
Texture t = new Texture(pm);
|
||||
pm.dispose();
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
stage.act(delta);
|
||||
stage.draw();
|
||||
}
|
||||
|
||||
@Override public void resize(int width, int height) { stage.getViewport().update(width, height, true); }
|
||||
@Override public void pause() {}
|
||||
@Override public void resume() {}
|
||||
@Override public void hide() {}
|
||||
@Override public void dispose() {
|
||||
stage.dispose();
|
||||
font.dispose();
|
||||
btnTex.dispose();
|
||||
btnLockedTex.dispose();
|
||||
btnGoldTex.dispose();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Screen;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
|
||||
public class MenuScreen implements Screen {
|
||||
private final MyGdxGame game;
|
||||
private SpriteBatch batch;
|
||||
private ShapeRenderer sr;
|
||||
private final OrthographicCamera cam;
|
||||
private BitmapFont buttonFont;
|
||||
private BitmapFont brandFont;
|
||||
private GlyphLayout layout;
|
||||
private final Rectangle btn = new Rectangle();
|
||||
private final Vector3 touch = new Vector3();
|
||||
private boolean initialized = false;
|
||||
private Texture texture;
|
||||
|
||||
public MenuScreen(MyGdxGame game) {
|
||||
this.game = game;
|
||||
this.cam = new OrthographicCamera();
|
||||
try {
|
||||
texture = new Texture("menu_bg.png");
|
||||
} catch (Exception e) {
|
||||
texture = null;
|
||||
}
|
||||
layout = new GlyphLayout();
|
||||
buttonFont = new BitmapFont();
|
||||
buttonFont.getData().setScale(2.5f);
|
||||
brandFont = new BitmapFont();
|
||||
brandFont.getData().setScale(5.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
if (!initialized) {
|
||||
this.batch = new SpriteBatch();
|
||||
this.sr = new ShapeRenderer();
|
||||
initialized = true;
|
||||
}
|
||||
resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(float delta) {
|
||||
if (!initialized) return;
|
||||
|
||||
if (Gdx.input.justTouched()) {
|
||||
cam.unproject(touch.set(Gdx.input.getX(), Gdx.input.getY(), 0));
|
||||
if (btn.contains(touch.x, touch.y)) {
|
||||
game.setScreen(new LevelSelectScreen(game));
|
||||
}
|
||||
}
|
||||
|
||||
Gdx.gl.glClearColor(0, 0, 0, 1);
|
||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
batch.setProjectionMatrix(cam.combined);
|
||||
batch.begin();
|
||||
if (texture != null) {
|
||||
batch.draw(texture, 0, 0, cam.viewportWidth, cam.viewportHeight);
|
||||
}
|
||||
batch.end();
|
||||
|
||||
sr.setProjectionMatrix(cam.combined);
|
||||
sr.begin(ShapeRenderer.ShapeType.Filled);
|
||||
sr.setColor(Color.DARK_GRAY);
|
||||
sr.rect(btn.x + 5, btn.y - 5, btn.width, btn.height);
|
||||
sr.setColor(Color.FOREST);
|
||||
sr.rect(btn.x, btn.y, btn.width, btn.height);
|
||||
sr.end();
|
||||
|
||||
batch.begin();
|
||||
drawButtonText(buttonFont, "START");
|
||||
brandFont.setColor(Color.WHITE);
|
||||
brandFont.draw(batch, "by Hikolit", 30, 80);
|
||||
batch.end();
|
||||
}
|
||||
|
||||
private void drawButtonText(BitmapFont font, String text) {
|
||||
font.setColor(Color.WHITE);
|
||||
layout.setText(font, text);
|
||||
float x = btn.x + (btn.width - layout.width) / 2f;
|
||||
float y = btn.y + (btn.height + layout.height) / 2f;
|
||||
font.draw(batch, text, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int w, int h) {
|
||||
cam.setToOrtho(false, w, h);
|
||||
btn.set(w / 2f - 200, h / 2f - 60, 400, 120);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (texture != null) texture.dispose();
|
||||
if (batch != null) batch.dispose();
|
||||
if (sr != null) sr.dispose();
|
||||
if (buttonFont != null) buttonFont.dispose();
|
||||
if (brandFont != null) brandFont.dispose();
|
||||
}
|
||||
|
||||
@Override public void pause() {}
|
||||
@Override public void resume() {}
|
||||
@Override public void hide() {}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.graphics.g3d.Model;
|
||||
import com.badlogic.gdx.graphics.g3d.ModelInstance;
|
||||
import com.badlogic.gdx.math.Intersector;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.math.collision.BoundingBox;
|
||||
import com.badlogic.gdx.math.collision.Ray;
|
||||
|
||||
class Mirror extends ModelInstance {
|
||||
public float angle;
|
||||
private final Matrix4 inv = new Matrix4();
|
||||
public static final BoundingBox bounds = new BoundingBox(new Vector3(-2.2f, -4f, -0.4f), new Vector3(2.2f, 4f, 0.4f));
|
||||
|
||||
public Mirror(Model m, float x, float y, float z, float a) {
|
||||
super(m);
|
||||
transform.setToTranslation(x, y, z);
|
||||
angle = a;
|
||||
update();
|
||||
}
|
||||
|
||||
public void rotate() {
|
||||
angle = (angle + 45f) % 360f;
|
||||
update();
|
||||
}
|
||||
|
||||
private void update() {
|
||||
Vector3 p = transform.getTranslation(new Vector3());
|
||||
transform.setToRotation(Vector3.Y, angle).setTranslation(p);
|
||||
inv.set(transform).inv();
|
||||
}
|
||||
|
||||
public boolean intersect(Ray r) {
|
||||
return Intersector.intersectRayBoundsFast(new Ray(new Vector3(r.origin).mul(inv), new Vector3(r.direction).rot(inv)), bounds);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.Game;
|
||||
import com.badlogic.gdx.graphics.g3d.ModelBatch;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
|
||||
public class MyGdxGame extends Game {
|
||||
public ModelBatch modelBatch;
|
||||
public ShapeRenderer shapeRenderer;
|
||||
public AudioManager audioManager;
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
audioManager = new AudioManager();
|
||||
modelBatch = new ModelBatch();
|
||||
shapeRenderer = new ShapeRenderer();
|
||||
setScreen(new MenuScreen(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
super.render();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (modelBatch != null) modelBatch.dispose();
|
||||
if (shapeRenderer != null) shapeRenderer.dispose();
|
||||
if (getScreen() != null) getScreen().dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.VertexAttributes;
|
||||
import com.badlogic.gdx.graphics.g3d.*;
|
||||
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
|
||||
import com.badlogic.gdx.graphics.g3d.utils.MeshPartBuilder;
|
||||
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.math.collision.Ray;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
public class SceneManager {
|
||||
public Array<Mirror> mirrors = new Array<>();
|
||||
public Array<Emitter> emitters = new Array<>();
|
||||
public Array<Target> targets = new Array<>();
|
||||
public Array<Wall> walls = new Array<>();
|
||||
|
||||
public ModelInstance floor;
|
||||
private final Model mirrorModel;
|
||||
private final Model floorModel;
|
||||
private final Model pyrModel;
|
||||
private final Model boxModel;
|
||||
private int currentLevel;
|
||||
|
||||
public static final float UNIT = 10.0f;
|
||||
public static final float MIRROR_H = 10.0f;
|
||||
public static final float LASER_HEIGHT = 5.0f;
|
||||
|
||||
public SceneManager() {
|
||||
ModelBuilder mb = new ModelBuilder();
|
||||
long attr = VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal;
|
||||
|
||||
mirrorModel = mb.createBox(6f, MIRROR_H, 1.0f, new Material(ColorAttribute.createDiffuse(Color.SKY)), attr);
|
||||
floorModel = mb.createBox(400f, 0.5f, 400f, new Material(ColorAttribute.createDiffuse(Color.DARK_GRAY)), attr);
|
||||
boxModel = mb.createBox(UNIT, UNIT, UNIT, new Material(ColorAttribute.createDiffuse(Color.GRAY)), attr);
|
||||
|
||||
mb.begin();
|
||||
MeshPartBuilder mpb = mb.part("pyr", GL20.GL_TRIANGLES, attr, new Material(ColorAttribute.createDiffuse(Color.WHITE)));
|
||||
Vector3 top = new Vector3(0, LASER_HEIGHT, 0), v1 = new Vector3(-2f,0,2f), v2 = new Vector3(2f,0,2f), v3 = new Vector3(2f,0,-2f), v4 = new Vector3(-2f,0,-2f);
|
||||
mpb.triangle(top, v1, v2); mpb.triangle(top, v2, v3); mpb.triangle(top, v3, v4); mpb.triangle(top, v4, v1);
|
||||
mpb.rect(v4, v3, v2, v1, new Vector3(0,-1,0));
|
||||
pyrModel = mb.end();
|
||||
|
||||
floor = new ModelInstance(floorModel, 0, -0.25f, 0);
|
||||
}
|
||||
|
||||
public void loadLevel(int lvl) {
|
||||
this.currentLevel = lvl;
|
||||
clearCurrentLevel();
|
||||
|
||||
switch (lvl) {
|
||||
case 1: addEmitter(-2, 0, 1, 0, 0); addMirror(0, 0, 45); addTarget(0, 2); break;
|
||||
case 2: addEmitter(-2, 0, 1, 0, 0); addWall(0, 0); addMirror(-1, 0, 45); addMirror(-1, 1, 45); addTarget(2, 1); break;
|
||||
case 3: addEmitter(-2, -2, 1, 0, 0); addMirror(1, -2, 45); addMirror(1, 0, 135); addTarget(-2, 0); break;
|
||||
case 4: addEmitter(-2, 2, 0, 0, -1); addWall(-1, 1); addWall(0, 1); addWall(1, 1); addMirror(-2, -1, 45); addMirror(2, -1, 45); addTarget(2, 2); break;
|
||||
case 5: addEmitter(-1, -2, 0, 0, 1); addMirror(-1, 2, 45); addMirror(1, 2, 45); addTarget(1, -2); break;
|
||||
case 6: addEmitter(-2, 0, 1, 0, 0); addEmitter(0, -2, 0, 0, 1); addMirror(1, 0, 45); addMirror(0, 1, 45); addTarget(1, 2); addTarget(2, 1); break;
|
||||
case 7: addEmitter(-2, 1, 1, 0, 0); addEmitter(-2, -1, 1, 0, 0); addWall(0, 0); addMirror(1, 1, 45); addMirror(1, -1, 45); addTarget(1, 2); addTarget(1, -2); break;
|
||||
case 8: addEmitter(-2, 2, 1, 0, 0); addEmitter(-2, -2, 1, 0, 0); addMirror(0, 2, 45); addMirror(0, -2, 45); addWall(0, 0); addTarget(2, 2); addTarget(2, -2); break;
|
||||
case 9: for(int i=-1; i<=1; i++) addWall(i, 0); addEmitter(-2, 1, 0, 0, -1); addEmitter(2, 1, 0, 0, -1); addMirror(-2, -1, 45); addMirror(2, -1, 45); addTarget(-1, -1); addTarget(1, -1); break;
|
||||
case 10: addEmitter(-1, -1, 1, 0, 0); addEmitter(1, 1, -1, 0, 0); addMirror(1, -1, 45); addMirror(-1, 1, 45); addTarget(1, 0); addTarget(-1, 0); break;
|
||||
case 11: addEmitter(-2, 2, 1, 0, 0); addWall(-1, 1); addWall(1, 1); addWall(0, 0); addMirror(2, 2, 45); addMirror(2, -2, 45); addMirror(-2, -2, 45); addTarget(-2, 0); break;
|
||||
case 12: addEmitter(0, 0, 1, 0, 0); addMirror(2, 0, 45); addMirror(2, 2, 135); addMirror(-2, 2, 45); addMirror(-2, -2, 135); addTarget(0, -2); break;
|
||||
case 13: addEmitter(-2, 2, 1, 0, 0); addEmitter(-2, 0, 1, 0, 0); addEmitter(-2, -2, 1, 0, 0); addMirror(0, 2, 45); addMirror(0, 0, 45); addMirror(0, -2, 45); addTarget(2, 2); addTarget(2, 0); addTarget(2, -2); break;
|
||||
case 14: for(int i=-1; i<=1; i++) for(int j=-1; j<=1; j++) addWall(i, j); addEmitter(-3, 0, 0, 0, 1); addMirror(-3, 3, 45); addMirror(3, 3, 45); addMirror(3, -3, 45); addMirror(-2, -3, 45); addMirror(-2, -2, 45); addTarget(0, -2); break;
|
||||
case 15: addEmitter(-2, 2, 0, 0, -1); addMirror(-2, -2, 45); addMirror(-1, -2, 45); addMirror(-1, 2, 45); addMirror(0, 2, 45); addMirror(0, -2, 45); addMirror(1, -2, 45); addMirror(1, 2, 45); addMirror(2, 2, 45); addTarget(2, -2); break;
|
||||
case 16: for(int x=-2; x<=2; x++) { addWall(x, 3); addWall(x, -3); } addEmitter(-1, 0, 0, 0, 1); addMirror(-1, 2, 45); addMirror(1, 2, 45); addMirror(1, -2, 45); addMirror(2, -2, 45); addMirror(2, 0, 45); addTarget(0, 0); break;
|
||||
case 17: addEmitter(-4, -5, 0, 0, 1); addMirror(-4, -3, 45); addMirror(-2, -3, 135); addMirror(-2, -1, 45); addMirror(2, -1, 135); addMirror(2, 1, 45); addMirror(-2, 1, 135); addMirror(-2, 3, 45); addMirror(2, 3, 135); addTarget(2, 5); break;
|
||||
case 18: addEmitter(-2, 1, 1, 0, 0); addEmitter(2, -1, -1, 0, 0); addMirror(0, 1, 45); addMirror(0, -1, 45); addMirror(-1, 0, 135); addMirror(1, 0, 135); addTarget(2, 1); addTarget(-2, -1); break;
|
||||
case 19: addEmitter(-5, 0, 1, 0, 0); addMirror(-3, 0, 45); addMirror(-3, -3, 135); addMirror(1, -3, 45); addMirror(1, 3, 135); addMirror(3, 3, 45); addMirror(3, 0, 135); addTarget(5, 0); break;
|
||||
case 20: int[][] heartWalls = {{0, -4}, {-1, -3}, {1, -3}, {-2, -2}, {2, -2}, {-3, -1}, {3, -1}, {-4, 0}, {4, 0}, {-4, 1}, {4, 1}, {-3, 2}, {3, 2}, {-2, 3}, {2, 3}, {-1, 3}, {1, 3}}; for(int[] p : heartWalls) addWall(p[0], p[1]); addEmitter(0, 5, 0, 0, -1); addMirror(0, 2, 45); addMirror(2, 2, 135); addMirror(2, -1, 45); addMirror(-2, -1, 135); addMirror(-2, 1, 45); addTarget(0, 0); break;
|
||||
case 21: addEmitter(-4, -4, 1, 0, 0); for(int i=-2; i<=2; i++) { addWall(i, -1); addWall(i, 1); } addMirror(4, -4, 45); addMirror(4, 0, 45); addMirror(-4, 0, 45); addMirror(-4, 4, 45); addTarget(4, 4); break;
|
||||
case 22: addEmitter(-5, -2, 1, 0, 0); for(int z=-5; z<=5; z++) { if(z != -2) addWall(-2, z); if(z != 2) addWall(2, z); } addMirror(0, -2, 45); addMirror(0, 2, 135); addTarget(5, 2); break;
|
||||
case 23: addEmitter(-5, -5, 1, 0, 0); addMirror(-2, -5, 45); addMirror(-2, 0, 135); addMirror(2, 0, 45); addMirror(2, 5, 135); addTarget(5, 5); break;
|
||||
case 24: for(int x=-1; x<=1; x++) for(int z=-1; z<=1; z++) addWall(x, z); addEmitter(-4, 0, 0, 0, 1); addMirror(-4, 4, 45); addMirror(4, 4, 135); addMirror(4, -4, 45); addMirror(0, -4, 135); addTarget(0, -2); break;
|
||||
case 25: addEmitter(-5, 0, 1, 0, 0); for(int i=-1; i<=1; i++) { addWall(i, 0); addWall(0, i); } addMirror(-3, 0, 45); addMirror(-3, 3, 45); addMirror(3, 3, 45); addMirror(3, 0, 45); addTarget(5, 0); break;
|
||||
case 26: addEmitter(-6, -3, 1, 0, 0); addEmitter(-6, 0, 1, 0, 0); addEmitter(-6, 3, 1, 0, 0); addMirror(0, -3, 45); addMirror(2, 0, 135); addMirror(4, 3, 45); addTarget(0, 6); addTarget(2, -4); addTarget(4, 8); break;
|
||||
case 27: addEmitter(-4, 0, 1, 0, 0); addMirror(0, 0, 45); addMirror(0, 2, 135); addTarget(-4, 2); break;
|
||||
case 28: addEmitter(-8, -4, 1, 0, 0); addEmitter(-8, 0, 1, 0, 0); addEmitter(-8, 4, 1, 0, 0); addMirror(-4, -4, 45); addMirror(0, 0, 135); addMirror(4, 4, 45); addTarget(-4, 2); addTarget(0, -6); addTarget(4, 10); break;
|
||||
case 29: addEmitter(-6, -4, 1, 0, 0); addEmitter(-6, 0, 1, 0, 0); addEmitter(-6, 4, 1, 0, 0); addMirror(-2, -4, 45); addMirror(-2, -2, 135); addMirror(0, 0, 45); addMirror(0, 2, 135); addMirror(2, 4, 45); addMirror(2, 6, 135); addTarget(6, -2); addTarget(6, 2); addTarget(6, 6); break;
|
||||
case 30: addEmitter(-6, -2, 1, 0, 0); addEmitter(-6, 2, 1, 0, 0); for(int x=-4; x<=4; x++) addWall(x, 0); addMirror(-2, -2, 45); addMirror(2, -2, 135); addMirror(-2, 2, 135); addMirror(2, 2, 45); addTarget(6, -2); addTarget(6, 2); break;
|
||||
case 31: addEmitter(-7, -7, 1, 0, 1); addEmitter(7, -7, -1, 0, 1); addEmitter(0, -10, 0, 0, 1); addMirror(-3, -3, 45); addMirror(3, -3, 135); addMirror(0, 0, 90); addTarget(-5, 5); addTarget(5, 5); addTarget(0, 8); break;
|
||||
case 32: addEmitter(-4, 0, 1, 0, 0); addEmitter(4, 0, -1, 0, 0); addEmitter(0, -4, 0, 0, 1); addMirror(-2, 0, 45); addMirror(2, 0, 135); addMirror(0, -2, 45); addTarget(-2, 5); addTarget(2, 5); addTarget(5, -2); break;
|
||||
case 33: addEmitter(-7, -3, 1, 0, 0); addEmitter(-7, 0, 1, 0, 0); addEmitter(-7, 3, 1, 0, 0); for(int z=-5; z<=5; z++) if(z % 3 != 0) addWall(0, z); addMirror(-3, -3, 45); addMirror(-3, 0, 135); addMirror(-3, 3, 45); addTarget(3, -3); addTarget(3, 0); addTarget(3, 3); break;
|
||||
case 34: addEmitter(-6, -6, 1, 0, 0); addEmitter(-6, 0, 1, 0, 0); addEmitter(-6, 6, 1, 0, 0); addMirror(0, -6, 45); addMirror(0, 0, 135); addMirror(0, 6, 45); addTarget(0, -3); addTarget(0, 3); addTarget(0, 9); break;
|
||||
case 35: addEmitter(-5, 0, 1, 0, 0); addEmitter(5, 0, -1, 0, 0); addMirror(0, 0, 45); addTarget(0, 3); addTarget(0, -3); break;
|
||||
case 36: addEmitter(-8, -4, 1, 0, 0); addEmitter(-8, 4, 1, 0, 0); for(int i=-2; i<=2; i++) addWall(0, i); addMirror(-4, -4, 45); addMirror(-4, 4, 135); addMirror(4, -4, 135); addMirror(4, 4, 45); addTarget(8, -4); addTarget(8, 4); break;
|
||||
case 37: addEmitter(-8, 0, 1, 0, 0); addMirror(-6, 0, 45); addMirror(-6, 4, 135); addMirror(0, 4, 45); addMirror(0, -4, 135); addMirror(6, -4, 45); addMirror(6, 0, 135); addTarget(9, 0); break;
|
||||
case 38: addEmitter(-7, -5, 1, 0, 0); addEmitter(-7, 0, 1, 0, 0); addEmitter(-7, 5, 1, 0, 0); addWall(-2, -2); addWall(-2, 2); addWall(2, -2); addWall(2, 2); addMirror(-4, -5, 45); addMirror(-4, 5, 135); addMirror(0, 0, 90); addTarget(7, -5); addTarget(7, 0); addTarget(7, 5); break;
|
||||
case 39: addEmitter(-5, -5, 1, 0, 0); for(int i=-3; i<=3; i++) { addWall(i, -3); addWall(i, 3); addWall(3, i); } addMirror(5, -5, 45); addMirror(5, 5, 135); addMirror(-5, 5, 45); addMirror(-5, 0, 135); addTarget(0, 0); break;
|
||||
case 40: addEmitter(-12, -12, 1, 0, 0);for(int i = -3; i <= 3; i++) {addWall(i, 0);addWall(0, i);}addMirror(-8, -12, 45);addMirror(-8, -8, 135);addMirror(-4, -8, 45);addMirror(-4, -4, 135);addMirror(4, -4, 45);addMirror(4, 4, 135);addMirror(8, 4, 45);addMirror(8, 8, 135);addMirror(12, 8, 45);addMirror(12, 12, 135);addMirror(-12, 12, 45);addMirror(-12, 0, 135);addTarget(12, 0);break; default: addEmitter(-1, 0, 1, 0, 0);addTarget(1, 0);break;
|
||||
}
|
||||
}
|
||||
private void clearCurrentLevel() {
|
||||
mirrors.clear(); emitters.clear(); targets.clear(); walls.clear();
|
||||
}
|
||||
|
||||
private void addEmitter(int gx, int gz, float dx, float dy, float dz) {
|
||||
emitters.add(new Emitter(pyrModel, gx * UNIT, 0, gz * UNIT, dx, dy, dz));
|
||||
}
|
||||
private void addTarget(int gx, int gz) {
|
||||
targets.add(new Target(pyrModel, gx * UNIT, 0, gz * UNIT));
|
||||
}
|
||||
private void addMirror(int gx, int gz, float angle) {
|
||||
mirrors.add(new Mirror(mirrorModel, gx * UNIT, MIRROR_H/2, gz * UNIT, angle));
|
||||
}
|
||||
private void addWall(int gx, int gz) {
|
||||
walls.add(new Wall(boxModel, gx * UNIT, UNIT / 2f, gz * UNIT));
|
||||
}
|
||||
|
||||
public void render(ModelBatch batch, Environment env) {
|
||||
batch.render(floor, env);
|
||||
for (Emitter e : emitters) batch.render(e.instance, env);
|
||||
for (Target t : targets) {
|
||||
t.updateVisual();
|
||||
batch.render(t.instance, env);
|
||||
}
|
||||
for (Mirror m : mirrors) batch.render(m, env);
|
||||
for (Wall w : walls) if(w.active) batch.render(w.instance, env);
|
||||
}
|
||||
|
||||
public void checkClick(Ray ray) {
|
||||
for (Mirror m : mirrors) if (m.intersect(ray)) { m.rotate(); break; }
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
mirrorModel.dispose(); floorModel.dispose(); pyrModel.dispose(); boxModel.dispose();
|
||||
}
|
||||
|
||||
public void nextLevel() {
|
||||
loadLevel((currentLevel % 40) + 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g3d.Model;
|
||||
import com.badlogic.gdx.graphics.g3d.ModelInstance;
|
||||
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
|
||||
class Target {
|
||||
public ModelInstance instance;
|
||||
public boolean hit = false;
|
||||
|
||||
public Target(Model m, float x, float y, float z) {
|
||||
instance = new ModelInstance(m, x, y, z);
|
||||
}
|
||||
|
||||
public Vector3 getPos() {
|
||||
return instance.transform.getTranslation(new Vector3()).add(0, SceneManager.LASER_HEIGHT, 0);
|
||||
}
|
||||
|
||||
public void updateVisual() {
|
||||
instance.nodes.get(0).parts.get(0).material.set(ColorAttribute.createDiffuse(hit ? Color.GREEN : Color.WHITE));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.mygdx.game;
|
||||
|
||||
import com.badlogic.gdx.graphics.g3d.Model;
|
||||
import com.badlogic.gdx.graphics.g3d.ModelInstance;
|
||||
|
||||
class Wall {
|
||||
public ModelInstance instance;
|
||||
public boolean active = true;
|
||||
|
||||
public Wall(Model m, float x, float y, float z) {
|
||||
instance = new ModelInstance(m, x, y, z);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user