commit 273f4a90f46924b094184a0b3ea0e176f00eec44 Author: Andrey Limasov Date: Tue Jun 16 11:02:07 2026 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d9d087 --- /dev/null +++ b/.gitignore @@ -0,0 +1,114 @@ +## Java + +*.class +*.war +*.ear +hs_err_pid* + +## Robovm +/ios/robovm-build/ + +## GWT +/html/war/ +/html/gwt-unitCache/ +.apt_generated/ +.gwt/ +gwt-unitCache/ +www-test/ +.gwt-tmp/ + +## Android Studio and Intellij and Android in general +/android/libs/armeabi-v7a/ +/android/libs/arm64-v8a/ +/android/libs/x86/ +/android/libs/x86_64/ +/android/gen/ +.idea/ +*.ipr +*.iws +*.iml +/android/out/ +com_crashlytics_export_strings.xml + +## Eclipse + +.classpath +.project +.metadata/ +/android/bin/ +/core/bin/ +/desktop/bin/ +/html/bin/ +/ios/bin/ +*.tmp +*.bak +*.swp +*~.nib +.settings/ +.loadpath +.externalToolBuilders/ +*.launch + +## NetBeans + +/nbproject/private/ +/android/nbproject/private/ +/core/nbproject/private/ +/desktop/nbproject/private/ +/html/nbproject/private/ +/ios/nbproject/private/ + +/build/ +/android/build/ +/core/build/ +/desktop/build/ +/html/build/ +/ios/build/ + +/nbbuild/ +/android/nbbuild/ +/core/nbbuild/ +/desktop/nbbuild/ +/html/nbbuild/ +/ios/nbbuild/ + +/dist/ +/android/dist/ +/core/dist/ +/desktop/dist/ +/html/dist/ +/ios/dist/ + +/nbdist/ +/android/nbdist/ +/core/nbdist/ +/desktop/nbdist/ +/html/nbdist/ +/ios/nbdist/ + +nbactions.xml +nb-configuration.xml + +## Gradle + +/local.properties +.gradle/ +gradle-app.setting +/build/ +/android/build/ +/core/build/ +/desktop/build/ +/html/build/ +/ios/build/ + +## OS Specific +.DS_Store +Thumbs.db + +## iOS +/ios/xcode/*.xcodeproj/* +!/ios/xcode/*.xcodeproj/xcshareddata +!/ios/xcode/*.xcodeproj/project.pbxproj +/ios/xcode/native/ +/ios/IOSLauncher.app +/ios/IOSLauncher.app.dSYM diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml new file mode 100644 index 0000000..1d1fc81 --- /dev/null +++ b/android/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/android/FakeDependency.jar b/android/FakeDependency.jar new file mode 100644 index 0000000..15cb0ec Binary files /dev/null and b/android/FakeDependency.jar differ diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..5c02f42 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,105 @@ +android { + + namespace "com.mygdx.game" + buildToolsVersion '33.0.0' + compileSdk 33 + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + aidl.srcDirs = ['src'] + renderscript.srcDirs = ['src'] + res.srcDirs = ['res'] + assets.srcDirs = ['../assets'] + jniLibs.srcDirs = ['libs'] + } + + + } + + packagingOptions { + exclude 'META-INF/robovm/ios/robovm.xml' + } + defaultConfig { + applicationId "com.mygdx.game" + minSdkVersion 14 + targetSdkVersion 33 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + + +// called every time gradle gets executed, takes the native dependencies of +// the natives configuration, and extracts them to the proper libs/ folders +// so they get packed with the APK. +tasks.register('copyAndroidNatives') { + doFirst { + file("libs/armeabi-v7a/").mkdirs() + file("libs/arm64-v8a/").mkdirs() + file("libs/x86_64/").mkdirs() + file("libs/x86/").mkdirs() + + configurations.natives.copy().files.each { jar -> + def outputDir = null + if (jar.name.endsWith("natives-arm64-v8a.jar")) outputDir = file("libs/arm64-v8a") + if (jar.name.endsWith("natives-armeabi-v7a.jar")) outputDir = file("libs/armeabi-v7a") + if (jar.name.endsWith("natives-x86_64.jar")) outputDir = file("libs/x86_64") + if (jar.name.endsWith("natives-x86.jar")) outputDir = file("libs/x86") + if (outputDir != null) { + copy { + from zipTree(jar) + into outputDir + include "*.so" + } + } + } + } +} + +tasks.matching { it.name.contains("merge") && it.name.contains("JniLibFolders") }.configureEach { packageTask -> + packageTask.dependsOn 'copyAndroidNatives' +} + +tasks.register('run', Exec) { + def path + def localProperties = project.file("../local.properties") + if (localProperties.exists()) { + Properties properties = new Properties() + localProperties.withInputStream { instr -> + properties.load(instr) + } + def sdkDir = properties.getProperty('sdk.dir') + if (sdkDir) { + path = sdkDir + } else { + path = "$System.env.ANDROID_HOME" + } + } else { + path = "$System.env.ANDROID_HOME" + } + + def adb = path + "/platform-tools/adb" + commandLine "$adb", 'shell', 'am', 'start', '-n', 'com.mygdx.game/com.mygdx.game.AndroidLauncher' + // Внутри модуля android + dependencies { + implementation project(":core") + api "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion" + + // Нативные библиотеки для Android + configurations.natives { + implementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a" + implementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a" + implementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86" + implementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64" + } + } +} + +eclipse.project.name = appName + "-android" diff --git a/android/ic_launcher-web.png b/android/ic_launcher-web.png new file mode 100644 index 0000000..8f0110d Binary files /dev/null and b/android/ic_launcher-web.png differ diff --git a/android/proguard-rules.pro b/android/proguard-rules.pro new file mode 100644 index 0000000..63c1adb --- /dev/null +++ b/android/proguard-rules.pro @@ -0,0 +1,38 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +-verbose + +-dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication + +# Required if using Gdx-Controllers extension +-keep class com.badlogic.gdx.controllers.android.AndroidControllers + +# Required if using Box2D extension +-keepclassmembers class com.badlogic.gdx.physics.box2d.World { + boolean contactFilter(long, long); + void beginContact(long); + void endContact(long); + void preSolve(long, long); + void postSolve(long, long); + boolean reportFixture(long); + float reportRayFixture(long, float, float, float, float, float); +} diff --git a/android/project.properties b/android/project.properties new file mode 100644 index 0000000..3fefa92 --- /dev/null +++ b/android/project.properties @@ -0,0 +1,9 @@ +# This file is used by the Eclipse ADT plugin. It is unnecessary for IDEA and Android Studio projects, which +# configure Proguard and the Android target via the build.gradle file. + +# To enable ProGuard to work with Eclipse ADT, uncomment this (available properties: sdk.dir, user.home) +# and ensure proguard.jar in the Android SDK is up to date (or alternately reduce the android target to 23 or lower): +# proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-rules.pro + +# Project target. +target=android-19 diff --git a/android/res/drawable-anydpi-v26/ic_launcher.xml b/android/res/drawable-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6c7313a --- /dev/null +++ b/android/res/drawable-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/android/res/drawable-anydpi-v26/ic_launcher_foreground.xml b/android/res/drawable-anydpi-v26/ic_launcher_foreground.xml new file mode 100644 index 0000000..5916ee8 --- /dev/null +++ b/android/res/drawable-anydpi-v26/ic_launcher_foreground.xml @@ -0,0 +1,40 @@ + + + + + + + + + diff --git a/android/res/drawable-hdpi/ic_launcher.png b/android/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..91f696b Binary files /dev/null and b/android/res/drawable-hdpi/ic_launcher.png differ diff --git a/android/res/drawable-mdpi/ic_launcher.png b/android/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..c1ab239 Binary files /dev/null and b/android/res/drawable-mdpi/ic_launcher.png differ diff --git a/android/res/drawable-xhdpi/ic_launcher.png b/android/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..2011cc0 Binary files /dev/null and b/android/res/drawable-xhdpi/ic_launcher.png differ diff --git a/android/res/drawable-xxhdpi/ic_launcher.png b/android/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..25fcef0 Binary files /dev/null and b/android/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/android/res/drawable-xxxhdpi/ic_launcher.png b/android/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..d109946 Binary files /dev/null and b/android/res/drawable-xxxhdpi/ic_launcher.png differ diff --git a/android/res/values-v21/styles.xml b/android/res/values-v21/styles.xml new file mode 100644 index 0000000..fcc6217 --- /dev/null +++ b/android/res/values-v21/styles.xml @@ -0,0 +1,6 @@ + + + + diff --git a/android/res/values/color.xml b/android/res/values/color.xml new file mode 100644 index 0000000..933353e --- /dev/null +++ b/android/res/values/color.xml @@ -0,0 +1,4 @@ + + + #FFFFFFFF + diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml new file mode 100644 index 0000000..889c244 --- /dev/null +++ b/android/res/values/strings.xml @@ -0,0 +1,6 @@ + + + + My GDX Game + + diff --git a/android/res/values/styles.xml b/android/res/values/styles.xml new file mode 100644 index 0000000..77377af --- /dev/null +++ b/android/res/values/styles.xml @@ -0,0 +1,6 @@ + + + + diff --git a/android/src/com/mygdx/game/AndroidLauncher.java b/android/src/com/mygdx/game/AndroidLauncher.java new file mode 100644 index 0000000..1614d64 --- /dev/null +++ b/android/src/com/mygdx/game/AndroidLauncher.java @@ -0,0 +1,15 @@ +package com.mygdx.game; + +import android.os.Bundle; + +import com.badlogic.gdx.backends.android.AndroidApplication; +import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; + +public class AndroidLauncher extends AndroidApplication { + @Override + protected void onCreate (Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + AndroidApplicationConfiguration config = new AndroidApplicationConfiguration(); + initialize(new MyGdxGame(), config); + } +} diff --git a/assets/Montserrat-Bold.ttf b/assets/Montserrat-Bold.ttf new file mode 100644 index 0000000..9a425b9 Binary files /dev/null and b/assets/Montserrat-Bold.ttf differ diff --git a/assets/bg.mp3 b/assets/bg.mp3 new file mode 100644 index 0000000..d0a089d Binary files /dev/null and b/assets/bg.mp3 differ diff --git a/assets/level_sq.png b/assets/level_sq.png new file mode 100644 index 0000000..620421a Binary files /dev/null and b/assets/level_sq.png differ diff --git a/assets/levels_bg.png b/assets/levels_bg.png new file mode 100644 index 0000000..e77e5fe Binary files /dev/null and b/assets/levels_bg.png differ diff --git a/assets/menu_bg.png b/assets/menu_bg.png new file mode 100644 index 0000000..8c7f44e Binary files /dev/null and b/assets/menu_bg.png differ diff --git a/assets/start_btn.png b/assets/start_btn.png new file mode 100644 index 0000000..1c49976 Binary files /dev/null and b/assets/start_btn.png differ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..edc25c3 --- /dev/null +++ b/build.gradle @@ -0,0 +1,93 @@ +buildscript { + + + repositories { + mavenLocal() + mavenCentral() + gradlePluginPortal() + maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.1.4' + + + } +} + +allprojects { + apply plugin: "eclipse" + + version = '1.0' + ext { + appName = "My GDX Game" + gdxVersion = '1.12.1' + roboVMVersion = '2.3.19' + box2DLightsVersion = '1.5' + ashleyVersion = '1.7.4' + aiVersion = '1.8.2' + gdxControllersVersion = '2.2.1' + } + + repositories { + mavenLocal() + mavenCentral() + google() + gradlePluginPortal() + maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + maven { url "https://oss.sonatype.org/content/repositories/releases/" } + maven { url "https://jitpack.io" } + } +} + +project(":desktop") { + apply plugin: "java-library" + + + dependencies { + implementation project(":core") + api "com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion" + api "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" + api "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop" + api "com.badlogicgames.gdx:gdx-bullet-platform:$gdxVersion:natives-desktop" + + } +} + +project(":android") { + apply plugin: "com.android.application" + + configurations { natives } + + dependencies { + implementation project(":core") + api "com.badlogicgames.gdx:gdx-backend-android:$gdxVersion" + natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-armeabi-v7a" + natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-arm64-v8a" + natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86" + natives "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-x86_64" + api "com.badlogicgames.gdx:gdx-freetype:$gdxVersion" + natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi-v7a" + natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-arm64-v8a" + natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86" + natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86_64" + api "com.badlogicgames.gdx:gdx-bullet:$gdxVersion" + natives "com.badlogicgames.gdx:gdx-bullet-platform:$gdxVersion:natives-armeabi-v7a" + natives "com.badlogicgames.gdx:gdx-bullet-platform:$gdxVersion:natives-arm64-v8a" + natives "com.badlogicgames.gdx:gdx-bullet-platform:$gdxVersion:natives-x86" + natives "com.badlogicgames.gdx:gdx-bullet-platform:$gdxVersion:natives-x86_64" + + } +} + +project(":core") { + apply plugin: "java-library" + + + dependencies { + api "com.badlogicgames.gdx:gdx:$gdxVersion" + api "com.badlogicgames.gdx:gdx-freetype:$gdxVersion" + api "com.badlogicgames.gdx:gdx-bullet:$gdxVersion" + + } +} diff --git a/core/build.gradle b/core/build.gradle new file mode 100644 index 0000000..cee7c36 --- /dev/null +++ b/core/build.gradle @@ -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" + + + +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/AudioManager.java b/core/src/com/mygdx/game/AudioManager.java new file mode 100644 index 0000000..70d5e7a --- /dev/null +++ b/core/src/com/mygdx/game/AudioManager.java @@ -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(); + } +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/Emitter.java b/core/src/com/mygdx/game/Emitter.java new file mode 100644 index 0000000..a1ea4be --- /dev/null +++ b/core/src/com/mygdx/game/Emitter.java @@ -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); + } +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/GameScreen.java b/core/src/com/mygdx/game/GameScreen.java new file mode 100644 index 0000000..7a3a10b --- /dev/null +++ b/core/src/com/mygdx/game/GameScreen.java @@ -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() {} +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/HelpUI.java b/core/src/com/mygdx/game/HelpUI.java new file mode 100644 index 0000000..55cc8d1 --- /dev/null +++ b/core/src/com/mygdx/game/HelpUI.java @@ -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(); + } +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/LaserRenderer.java b/core/src/com/mygdx/game/LaserRenderer.java new file mode 100644 index 0000000..7748aca --- /dev/null +++ b/core/src/com/mygdx/game/LaserRenderer.java @@ -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> 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 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 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 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); + } +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/LevelSelectScreen.java b/core/src/com/mygdx/game/LevelSelectScreen.java new file mode 100644 index 0000000..506a1b7 --- /dev/null +++ b/core/src/com/mygdx/game/LevelSelectScreen.java @@ -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(); + + } +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/MenuScreen.java b/core/src/com/mygdx/game/MenuScreen.java new file mode 100644 index 0000000..4de3bad --- /dev/null +++ b/core/src/com/mygdx/game/MenuScreen.java @@ -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() {} +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/Mirror.java b/core/src/com/mygdx/game/Mirror.java new file mode 100644 index 0000000..735f041 --- /dev/null +++ b/core/src/com/mygdx/game/Mirror.java @@ -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); + } +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/MyGdxGame.java b/core/src/com/mygdx/game/MyGdxGame.java new file mode 100644 index 0000000..3ac16f2 --- /dev/null +++ b/core/src/com/mygdx/game/MyGdxGame.java @@ -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(); + } +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/SceneManager.java b/core/src/com/mygdx/game/SceneManager.java new file mode 100644 index 0000000..f21d886 --- /dev/null +++ b/core/src/com/mygdx/game/SceneManager.java @@ -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 mirrors = new Array<>(); + public Array emitters = new Array<>(); + public Array targets = new Array<>(); + public Array 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); + } +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/Target.java b/core/src/com/mygdx/game/Target.java new file mode 100644 index 0000000..6bc5eff --- /dev/null +++ b/core/src/com/mygdx/game/Target.java @@ -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)); + } +} \ No newline at end of file diff --git a/core/src/com/mygdx/game/Wall.java b/core/src/com/mygdx/game/Wall.java new file mode 100644 index 0000000..14ec7e2 --- /dev/null +++ b/core/src/com/mygdx/game/Wall.java @@ -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); + } +} \ No newline at end of file diff --git a/core/src/com/mygdx/game1.zip b/core/src/com/mygdx/game1.zip new file mode 100644 index 0000000..8a98256 Binary files /dev/null and b/core/src/com/mygdx/game1.zip differ diff --git a/desktop/build.gradle b/desktop/build.gradle new file mode 100644 index 0000000..a7f0abe --- /dev/null +++ b/desktop/build.gradle @@ -0,0 +1,49 @@ +sourceCompatibility = 1.8 +sourceSets.main.java.srcDirs = [ "src/" ] +sourceSets.main.resources.srcDirs = ["../assets"] + +project.ext.mainClassName = "com.mygdx.game.DesktopLauncher" +project.ext.assetsDir = new File("../assets") + +import org.gradle.internal.os.OperatingSystem + +tasks.register('run', JavaExec) { + dependsOn classes + mainClass = project.mainClassName + classpath = sourceSets.main.runtimeClasspath + standardInput = System.in + workingDir = project.assetsDir + ignoreExitValue = true + + if (OperatingSystem.current() == OperatingSystem.MAC_OS) { + // Required to run on macOS + jvmArgs += "-XstartOnFirstThread" + } +} + +tasks.register('debug', JavaExec) { + dependsOn classes + mainClass = project.mainClassName + classpath = sourceSets.main.runtimeClasspath + standardInput = System.in + workingDir = project.assetsDir + ignoreExitValue = true + debug = true +} + +tasks.register('dist', Jar) { + duplicatesStrategy(DuplicatesStrategy.EXCLUDE) + manifest { + attributes 'Main-Class': project.mainClassName + } + dependsOn configurations.runtimeClasspath + from { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } + with jar +} + + +dist.dependsOn classes + +eclipse.project.name = appName + "-desktop" diff --git a/desktop/src/com/mygdx/game/DesktopLauncher.java b/desktop/src/com/mygdx/game/DesktopLauncher.java new file mode 100644 index 0000000..2b0302b --- /dev/null +++ b/desktop/src/com/mygdx/game/DesktopLauncher.java @@ -0,0 +1,14 @@ +package com.mygdx.game; + +import com.badlogic.gdx.ApplicationListener; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; +import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration; + +// Please note that on macOS your application needs to be started with the -XstartOnFirstThread JVM argument +public class DesktopLauncher { + public static void main (String[] arg) { + Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration(); + config.setForegroundFPS(60); + config.setTitle("My GDX Game"); + new Lwjgl3Application(new MyGdxGame(), config); + }} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..92e8269 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,5 @@ +org.gradle.daemon=true +org.gradle.jvmargs=-Xms128m -Xmx1500m +org.gradle.configureondemand=false +android.useAndroidX=true +android.enableJetifier=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..d64cd49 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..f9939dc --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Dec 23 22:34:58 MSK 2025 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..1aa94a4 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..93e3f59 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/native/0d407fdbe67a94daf76414ababcb853783967236a71b16ec16e742cd7a986fd3/windows-amd64/native-platform-file-events.dll b/native/0d407fdbe67a94daf76414ababcb853783967236a71b16ec16e742cd7a986fd3/windows-amd64/native-platform-file-events.dll new file mode 100644 index 0000000..3177846 Binary files /dev/null and b/native/0d407fdbe67a94daf76414ababcb853783967236a71b16ec16e742cd7a986fd3/windows-amd64/native-platform-file-events.dll differ diff --git a/native/0d407fdbe67a94daf76414ababcb853783967236a71b16ec16e742cd7a986fd3/windows-amd64/native-platform-file-events.dll.lock b/native/0d407fdbe67a94daf76414ababcb853783967236a71b16ec16e742cd7a986fd3/windows-amd64/native-platform-file-events.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/0d407fdbe67a94daf76414ababcb853783967236a71b16ec16e742cd7a986fd3/windows-amd64/native-platform-file-events.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/100fb08df4bc3b14c8652ba06237920a3bd2aa13389f12d3474272988ae205f9/windows-amd64/native-platform-file-events.dll b/native/100fb08df4bc3b14c8652ba06237920a3bd2aa13389f12d3474272988ae205f9/windows-amd64/native-platform-file-events.dll new file mode 100644 index 0000000..931e339 Binary files /dev/null and b/native/100fb08df4bc3b14c8652ba06237920a3bd2aa13389f12d3474272988ae205f9/windows-amd64/native-platform-file-events.dll differ diff --git a/native/100fb08df4bc3b14c8652ba06237920a3bd2aa13389f12d3474272988ae205f9/windows-amd64/native-platform-file-events.dll.lock b/native/100fb08df4bc3b14c8652ba06237920a3bd2aa13389f12d3474272988ae205f9/windows-amd64/native-platform-file-events.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/100fb08df4bc3b14c8652ba06237920a3bd2aa13389f12d3474272988ae205f9/windows-amd64/native-platform-file-events.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/19/windows-amd64/native-platform.dll b/native/19/windows-amd64/native-platform.dll new file mode 100644 index 0000000..e8675da Binary files /dev/null and b/native/19/windows-amd64/native-platform.dll differ diff --git a/native/19/windows-amd64/native-platform.dll.lock b/native/19/windows-amd64/native-platform.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/19/windows-amd64/native-platform.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/38dada09dfb8b06ba9b0570ebf7e218e3eb74d4ef43ca46872605cf95ebc2f47/windows-amd64/native-platform-file-events.dll b/native/38dada09dfb8b06ba9b0570ebf7e218e3eb74d4ef43ca46872605cf95ebc2f47/windows-amd64/native-platform-file-events.dll new file mode 100644 index 0000000..408283d Binary files /dev/null and b/native/38dada09dfb8b06ba9b0570ebf7e218e3eb74d4ef43ca46872605cf95ebc2f47/windows-amd64/native-platform-file-events.dll differ diff --git a/native/38dada09dfb8b06ba9b0570ebf7e218e3eb74d4ef43ca46872605cf95ebc2f47/windows-amd64/native-platform-file-events.dll.lock b/native/38dada09dfb8b06ba9b0570ebf7e218e3eb74d4ef43ca46872605cf95ebc2f47/windows-amd64/native-platform-file-events.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/38dada09dfb8b06ba9b0570ebf7e218e3eb74d4ef43ca46872605cf95ebc2f47/windows-amd64/native-platform-file-events.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/5664cfc778a61ccfe75a443a1ab52a65af34e5dc3c78e0209fed803814484fcb/windows-amd64/native-platform-file-events.dll b/native/5664cfc778a61ccfe75a443a1ab52a65af34e5dc3c78e0209fed803814484fcb/windows-amd64/native-platform-file-events.dll new file mode 100644 index 0000000..d2b56e5 Binary files /dev/null and b/native/5664cfc778a61ccfe75a443a1ab52a65af34e5dc3c78e0209fed803814484fcb/windows-amd64/native-platform-file-events.dll differ diff --git a/native/5664cfc778a61ccfe75a443a1ab52a65af34e5dc3c78e0209fed803814484fcb/windows-amd64/native-platform-file-events.dll.lock b/native/5664cfc778a61ccfe75a443a1ab52a65af34e5dc3c78e0209fed803814484fcb/windows-amd64/native-platform-file-events.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/5664cfc778a61ccfe75a443a1ab52a65af34e5dc3c78e0209fed803814484fcb/windows-amd64/native-platform-file-events.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64-min/native-platform.dll b/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64-min/native-platform.dll new file mode 100644 index 0000000..57ab86e Binary files /dev/null and b/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64-min/native-platform.dll differ diff --git a/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64-min/native-platform.dll.lock b/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64-min/native-platform.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64-min/native-platform.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64/native-platform.dll b/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64/native-platform.dll new file mode 100644 index 0000000..374b07e Binary files /dev/null and b/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64/native-platform.dll differ diff --git a/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64/native-platform.dll.lock b/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64/native-platform.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/68d5fa5c4cc2d200863cafc0d521ce42e7d3e7ee720ec0a83991735586a16f82/windows-amd64/native-platform.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64-min/native-platform.dll b/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64-min/native-platform.dll new file mode 100644 index 0000000..e793d41 Binary files /dev/null and b/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64-min/native-platform.dll differ diff --git a/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64-min/native-platform.dll.lock b/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64-min/native-platform.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64-min/native-platform.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64/native-platform.dll b/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64/native-platform.dll new file mode 100644 index 0000000..ccc4b06 Binary files /dev/null and b/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64/native-platform.dll differ diff --git a/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64/native-platform.dll.lock b/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64/native-platform.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/c067742578af261105cb4f569cf0c3c89f3d7b1fecec35dd04571415982c5e48/windows-amd64/native-platform.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/e1d6ef7f7dcc3fd88c89a11ec53ec762bb8ba0a96d01ffa2cd45eb1d1d8dd5c5/windows-amd64/native-platform.dll b/native/e1d6ef7f7dcc3fd88c89a11ec53ec762bb8ba0a96d01ffa2cd45eb1d1d8dd5c5/windows-amd64/native-platform.dll new file mode 100644 index 0000000..81c5ee2 Binary files /dev/null and b/native/e1d6ef7f7dcc3fd88c89a11ec53ec762bb8ba0a96d01ffa2cd45eb1d1d8dd5c5/windows-amd64/native-platform.dll differ diff --git a/native/e1d6ef7f7dcc3fd88c89a11ec53ec762bb8ba0a96d01ffa2cd45eb1d1d8dd5c5/windows-amd64/native-platform.dll.lock b/native/e1d6ef7f7dcc3fd88c89a11ec53ec762bb8ba0a96d01ffa2cd45eb1d1d8dd5c5/windows-amd64/native-platform.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/e1d6ef7f7dcc3fd88c89a11ec53ec762bb8ba0a96d01ffa2cd45eb1d1d8dd5c5/windows-amd64/native-platform.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/e376f236ea51e6404a007f0833ffe2c6e607c4080706a723a18a27aeea778392/windows-amd64/native-platform-file-events.dll b/native/e376f236ea51e6404a007f0833ffe2c6e607c4080706a723a18a27aeea778392/windows-amd64/native-platform-file-events.dll new file mode 100644 index 0000000..a750809 Binary files /dev/null and b/native/e376f236ea51e6404a007f0833ffe2c6e607c4080706a723a18a27aeea778392/windows-amd64/native-platform-file-events.dll differ diff --git a/native/e376f236ea51e6404a007f0833ffe2c6e607c4080706a723a18a27aeea778392/windows-amd64/native-platform-file-events.dll.lock b/native/e376f236ea51e6404a007f0833ffe2c6e607c4080706a723a18a27aeea778392/windows-amd64/native-platform-file-events.dll.lock new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/native/e376f236ea51e6404a007f0833ffe2c6e607c4080706a723a18a27aeea778392/windows-amd64/native-platform-file-events.dll.lock @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/native/jansi/1.18/windows64/jansi.dll b/native/jansi/1.18/windows64/jansi.dll new file mode 100644 index 0000000..cfe23c9 Binary files /dev/null and b/native/jansi/1.18/windows64/jansi.dll differ diff --git a/native/jna/win32-amd64/jnidispatch.dll b/native/jna/win32-amd64/jnidispatch.dll new file mode 100644 index 0000000..fdaca3d Binary files /dev/null and b/native/jna/win32-amd64/jnidispatch.dll differ diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..77ae463 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include 'desktop', 'android', 'core' \ No newline at end of file