Merge branch 'adventure' into 'master'

Adventure mode

See merge request core-developers/forge!5584
This commit is contained in:
Michael Kamensky
2021-10-20 04:54:04 +00:00
618 changed files with 37859 additions and 79 deletions

6
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,6 @@
deploy:
image: maven:3.6-jdk-8
script:
- 'mvn -U -B clean -P windows-linux install'
only:
- master

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

233
forge-adventure/pom.xml Normal file
View File

@@ -0,0 +1,233 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>forge</artifactId>
<groupId>forge</groupId>
<version>1.6.46-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>forge-adventure</artifactId>
<packaging>jar</packaging>
<name>Forge Adventure</name>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>${project.basedir}</directory>
<includes>
<include>**/*.vert</include>
<include>**/*.frag</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.akathist.maven.plugins.launch4j</groupId>
<artifactId>launch4j-maven-plugin</artifactId>
<version>1.7.25</version>
<executions>
<execution>
<id>l4j-adv</id>
<phase>package</phase>
<goals>
<goal>launch4j</goal>
</goals>
<configuration>
<headerType>gui</headerType>
<outfile>${project.build.directory}/forge-adventure.exe</outfile>
<jar>${project.build.finalName}-jar-with-dependencies.jar</jar>
<dontWrapJar>true</dontWrapJar>
<errTitle>forge</errTitle>
<icon>src/main/config/forge-adventure.ico</icon>
<classPath>
<mainClass>forge.adventure.Main</mainClass>
<addDependencies>false</addDependencies>
<preCp>anything</preCp>
</classPath>
<jre>
<minVersion>1.8.0</minVersion>
<maxHeapSize>4096</maxHeapSize>
<opts>
<opt>-Dfile.encoding=UTF-8</opt>
</opts>
</jre>
<versionInfo>
<fileVersion>
1.0.0.0
</fileVersion>
<txtFileVersion>
1.0.0.0
</txtFileVersion>
<fileDescription>Forge</fileDescription>
<copyright>Forge</copyright>
<productVersion>
1.0.0.0
</productVersion>
<txtProductVersion>
1.0.0.0
</txtProductVersion>
<productName>forge-adventure</productName>
<internalName>forge-adventure</internalName>
<originalFilename>forge-adventure.exe</originalFilename>
</versionInfo>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<basedir>${basedir}/${configSourceDirectory}</basedir>
<filesToInclude>forge-adventure.sh, forge-adventure.command</filesToInclude>
<outputBasedir>${project.build.directory}</outputBasedir>
<outputDir>.</outputDir>
<regex>false</regex>
<replacements>
<replacement>
<token>$project.build.finalName$</token>
<value>${project.build.finalName}-jar-with-dependencies.jar</value>
</replacement>
</replacements>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<attach>false</attach>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>forge.adventure.Main</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- this is used for inheritance merges -->
<phase>package</phase>
<!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.github.jetopto1</groupId>
<artifactId>cling</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.badlogicgames.gdx</groupId>
<artifactId>gdx</artifactId>
<version>1.10.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.badlogicgames.gdx</groupId>
<artifactId>gdx-platform</artifactId>
<version>1.10.0</version>
<classifier>natives-desktop</classifier>
</dependency>
<dependency>
<groupId>com.badlogicgames.gdx</groupId>
<artifactId>gdx-freetype</artifactId>
<version>1.10.0</version>
</dependency>
<dependency>
<groupId>com.badlogicgames.gdx</groupId>
<artifactId>gdx-backend-lwjgl3</artifactId>
<version>1.10.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.badlogicgames.gdx</groupId>
<artifactId>gdx-freetype-platform</artifactId>
<version>1.10.0</version>
<classifier>natives-desktop</classifier>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-game</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-ai</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-gui</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-gui-mobile</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.github.raeleus.TenPatch</groupId>
<artifactId>tenpatch</artifactId>
<version>5.2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>22.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-gui-mobile</artifactId>
<version>1.6.46-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>

View File

@@ -0,0 +1,14 @@
# ideally this should be using HTTPS, but this is fine for now
dsn=http://a0b8dbad9b8a49cfa51bf65d462e8dae@sentry.cardforge.org:9000/2
stacktrace.app.packages=forge
# where to store events if offline or can't reach the above server
buffer.dir=sentry-events
buffer.size=100
# allow ample time for graceful shutdown
buffer.shutdowntimeout=5000
async.shutdowntimeout=5000
# allow longer messages
maxmessagelength=1500

View File

@@ -0,0 +1,15 @@
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform float u_grayness;
void main() {
vec4 c = v_color * texture2D(u_texture, v_texCoords);
float grey = dot( c.rgb, vec3(0.22, 0.707, 0.071) );
vec3 blendedColor = mix(c.rgb, vec3(grey), u_grayness);
gl_FragColor = vec4(blendedColor.rgb, c.a);
}

View File

@@ -0,0 +1,14 @@
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
varying vec4 v_color;
varying vec2 v_texCoords;
void main() {
v_color = a_color;
v_texCoords = a_texCoord0;
gl_Position = u_projTrans * a_position;
}

View File

@@ -0,0 +1,40 @@
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
uniform sampler2D u_texture;
uniform vec2 u_viewportInverse;
uniform vec3 u_color;
uniform float u_offset;
uniform float u_step;
varying vec4 v_color;
varying vec2 v_texCoord;
#define ALPHA_VALUE_BORDER 0.5
void main() {
vec2 T = v_texCoord.xy;
float alpha = 0.0;
bool allin = true;
for( float ix = -u_offset; ix < u_offset; ix += u_step )
{
for( float iy = -u_offset; iy < u_offset; iy += u_step )
{
float newAlpha = texture2D(u_texture, T + vec2(ix, iy) * u_viewportInverse).a;
allin = allin && newAlpha > ALPHA_VALUE_BORDER;
if (newAlpha > ALPHA_VALUE_BORDER && newAlpha >= alpha)
{
alpha = newAlpha;
}
}
}
if (allin)
{
alpha = 0.0;
}
gl_FragColor = vec4(u_color,alpha);
}

View File

@@ -0,0 +1,16 @@
uniform mat4 u_projTrans;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
attribute vec4 a_color;
varying vec4 v_color;
varying vec2 v_texCoord;
uniform vec2 u_viewportInverse;
void main() {
gl_Position = u_projTrans * a_position;
v_texCoord = a_texCoord0;
v_color = a_color;
}

View File

@@ -0,0 +1,23 @@
#ifdef GL_ES
#define PRECISION mediump
precision PRECISION float;
precision PRECISION int;
#else
#define PRECISION
#endif
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform float u_amount;
uniform float u_speed;
uniform float u_time;
void main () {
vec2 uv = v_texCoords;
uv.y += (cos((uv.y + (u_time * 0.04 * u_speed)) * 45.0) * 0.0019 * u_amount) + (cos((uv.y + (u_time * 0.1 * u_speed)) * 10.0) * 0.002 * u_amount);
uv.x += (sin((uv.y + (u_time * 0.07 * u_speed)) * 15.0) * 0.0029 * u_amount) + (sin((uv.y + (u_time * 0.1 * u_speed)) * 15.0) * 0.002 * u_amount);
gl_FragColor = texture2D(u_texture, uv);
}

View File

@@ -0,0 +1,57 @@
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform float u_time;
uniform float u_speed;
uniform float u_amount;
uniform vec2 u_viewport;
uniform vec2 u_position;
float random2d(vec2 n) {
return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
}
float randomRange (in vec2 seed, in float min, in float max) {
return min + random2d(seed) * (max - min);
}
float insideRange(float v, float bottom, float top) {
return step(bottom, v) - step(top, v);
}
void main()
{
float time = floor(u_time * u_speed * 60.0);
vec3 outCol = texture2D(u_texture, v_texCoords).rgb;
float maxOffset = u_amount/2.0;
for (float i = 0.0; i < 2.0; i += 1.0) {
float sliceY = random2d(vec2(time, 2345.0 + float(i)));
float sliceH = random2d(vec2(time, 9035.0 + float(i))) * 0.25;
float hOffset = randomRange(vec2(time, 9625.0 + float(i)), -maxOffset, maxOffset);
vec2 uvOff = v_texCoords;
uvOff.x += hOffset;
if (insideRange(v_texCoords.y, sliceY, fract(sliceY+sliceH)) == 1.0){
outCol = texture2D(u_texture, uvOff).rgb;
}
}
float maxColOffset = u_amount / 6.0;
float rnd = random2d(vec2(time , 9545.0));
vec2 colOffset = vec2(randomRange(vec2(time , 9545.0), -maxColOffset, maxColOffset),
randomRange(vec2(time , 7205.0), -maxColOffset, maxColOffset));
if (rnd < 0.33) {
outCol.r = texture2D(u_texture, v_texCoords + colOffset).r;
} else if (rnd < 0.66) {
outCol.g = texture2D(u_texture, v_texCoords + colOffset).g;
} else {
outCol.b = texture2D(u_texture, v_texCoords + colOffset).b;
}
gl_FragColor = vec4(outCol, 1.0);
}

View File

@@ -0,0 +1,3 @@
#!/bin/sh
cd $(dirname "${0}")
java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View File

@@ -0,0 +1,3 @@
#!/bin/sh
cd $(dirname "${0}")
java -Xmx4096m -Dfile.encoding=UTF-8 -jar $project.build.finalName$

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

View File

@@ -0,0 +1,195 @@
package forge.adventure;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ScreenUtils;
import forge.Graphics;
import forge.adventure.scene.ForgeScene;
import forge.adventure.scene.Scene;
import forge.adventure.scene.SceneType;
import forge.adventure.util.Config;
/**
* Application adapter the handle switching and fading between scenes
*/
public class AdventureApplicationAdapter extends ApplicationAdapter {
public static AdventureApplicationAdapter instance;
Scene currentScene = null;
Array<Scene> lastScene = new Array<>();
private int currentWidth;
private int currentHeight;
private float animationTimeout;
Batch animationBatch;
Texture transitionTexture;
TextureRegion lastScreenTexture;
private boolean sceneWasSwapped =false;
private Graphics graphics;
public Graphics getGraphics()
{
if(graphics==null)
graphics=new Graphics();
return graphics;
}
public TextureRegion getLastScreenTexture() {
return lastScreenTexture;
}
public AdventureApplicationAdapter() {
instance = this;
}
public int getCurrentWidth() {
return currentWidth;
}
public int getCurrentHeight() {
return currentHeight;
}
public Scene getCurrentScene() {
return currentScene;
}
@Override
public void resize(int w, int h) {
currentWidth = w;
currentHeight = h;
StartAdventure.app.resize(w, h);
super.resize(w, h);
}
public boolean switchScene(Scene newScene) {
if (currentScene != null) {
if (!currentScene.leave())
return false;
lastScene.add(currentScene);
}
storeScreen();
sceneWasSwapped =true;
currentScene = newScene;
currentScene.enter();
return true;
}
private void storeScreen() {
if(!(currentScene instanceof ForgeScene))
lastScreenTexture = ScreenUtils.getFrameBufferTexture();
}
public void resLoaded() {
for (forge.adventure.scene.SceneType entry : SceneType.values()) {
entry.instance.resLoaded();
}
//AdventureApplicationAdapter.CurrentAdapter.switchScene(SceneType.RewardScene.instance);
switchScene(SceneType.StartScene.instance);
animationBatch=new SpriteBatch();
transitionTexture =new Texture(Config.instance().getFile("ui/transition.png"));
}
@Override
public void create() {
Pixmap pm = new Pixmap(Config.instance().getFile("skin/cursor.png"));
Gdx.graphics.setCursor(Gdx.graphics.newCursor(pm, 0, 0));
pm.dispose();
for (forge.adventure.scene.SceneType entry : SceneType.values()) {
entry.instance.create();
}
}
@Override
public void render() {
float delta=Gdx.graphics.getDeltaTime();
float transitionTime = 0.2f;
if(sceneWasSwapped)
{
sceneWasSwapped =false;
animationTimeout= transitionTime;
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
return;
}
if(animationTimeout>=0)
{
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
animationBatch.begin();
animationTimeout-=delta;
animationBatch.setColor(1,1,1,1);
animationBatch.draw(lastScreenTexture,0,0, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
animationBatch.setColor(1,1,1,1-(1/ transitionTime)*animationTimeout);
animationBatch.draw(transitionTexture,0,0, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
animationBatch.draw(transitionTexture,0,0, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
animationBatch.end();
if(animationTimeout<0)
{
currentScene.render();
storeScreen();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
else
{
return;
}
}
if(animationTimeout>=-transitionTime)
{
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
animationBatch.begin();
animationTimeout-=delta;
animationBatch.setColor(1,1,1,1);
animationBatch.draw(lastScreenTexture,0,0, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
animationBatch.setColor(1,1,1,(1/ transitionTime)*(animationTimeout+ transitionTime));
animationBatch.draw(transitionTexture,0,0, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
animationBatch.draw(transitionTexture,0,0, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
animationBatch.end();
return;
}
currentScene.render();
currentScene.act(delta);
}
@Override
public void dispose() {
for (forge.adventure.scene.SceneType entry : SceneType.values()) {
entry.instance.dispose();
}
System.exit(0);
}
private Scene getLastScene() {
return lastScene.size==0?null: lastScene.get(lastScene.size-1);
}
public Scene switchToLast() {
if(lastScene.size!=0)
{
storeScreen();
currentScene = lastScene.get(lastScene.size-1);
currentScene.enter();
sceneWasSwapped =true;
lastScene.removeIndex(lastScene.size-1);
return currentScene;
}
return null;
}
}

View File

@@ -0,0 +1,91 @@
package forge.adventure;
import com.badlogic.gdx.Gdx;
import forge.interfaces.IDeviceAdapter;
import forge.util.FileUtil;
import forge.util.OperatingSystem;
import forge.util.RestartUtil;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Adapter for desktop usage
*/
public class DesktopAdapter implements IDeviceAdapter {
private final String switchOrientationFile;
public DesktopAdapter(String switchOrientationFile0) {
switchOrientationFile = switchOrientationFile0;
}
//just assume desktop always connected to wifi
@Override
public boolean isConnectedToInternet() {
return true;
}
@Override
public boolean isConnectedToWifi() {
return true;
}
@Override
public String getDownloadsDir() {
return System.getProperty("user.home") + "/Downloads/";
}
@Override
public boolean openFile(String filename) {
try {
Desktop.getDesktop().open(new File(filename));
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
public void restart() {
if (RestartUtil.prepareForRestart()) {
Gdx.app.exit();
}
}
@Override
public void exit() {
Gdx.app.exit(); //can just use Gdx.app.exit for desktop
}
@Override
public boolean isTablet() {
return true; //treat desktop the same as a tablet
}
@Override
public void setLandscapeMode(boolean landscapeMode) {
//create file to indicate that landscape mode should be used
if (landscapeMode) {
FileUtil.writeFile(switchOrientationFile, "1");
} else {
FileUtil.deleteFile(switchOrientationFile);
}
}
@Override
public void preventSystemSleep(boolean preventSleep) {
OperatingSystem.preventSystemSleep(preventSleep);
}
@Override
public void convertToJPEG(InputStream input, OutputStream output) throws IOException {
BufferedImage image = ImageIO.read(input);
ImageIO.write(image, "jpg", output);
}
}

View File

@@ -0,0 +1,300 @@
package forge.adventure;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Clipboard;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.utils.Clipboard;
import forge.Forge;
import forge.FrameRate;
import forge.GuiMobile;
import forge.adventure.scene.SettingsScene;
import forge.adventure.util.Config;
import forge.assets.AssetsDownloader;
import forge.assets.FSkin;
import forge.assets.FSkinFont;
import forge.assets.ImageCache;
import forge.error.ExceptionHandler;
import forge.gui.FThreads;
import forge.gui.GuiBase;
import forge.interfaces.IDeviceAdapter;
import forge.localinstance.properties.ForgeConstants;
import forge.localinstance.properties.ForgePreferences;
import forge.model.FModel;
import forge.screens.FScreen;
import forge.screens.SplashScreen;
import forge.sound.MusicPlaylist;
import forge.sound.SoundSystem;
import forge.util.BuildInfo;
import forge.util.CardTranslation;
import forge.util.FileUtil;
import forge.util.Localizer;
import io.sentry.Sentry;
import io.sentry.SentryClient;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
/**
* Wrapper to start forge first (splash screen and resources loading)
*
*/
class StartAdventure extends AdventureApplicationAdapter {
private static final int continuousRenderingCount = 1; //initialize to 1 since continuous rendering is the default
private static final Deque<FScreen> Dscreens = new ArrayDeque<>();
private static final boolean isloadingaMatch = false;
public static String extrawide = "default";
public static float heigtModifier = 0.0f;
public static boolean showFPS = false;
public static boolean altPlayerLayout = false;
public static boolean altZoneTabs = false;
public static String enableUIMask = "Crop";
public static boolean enablePreloadExtendedArt = false;
public static boolean isTabletDevice = false;
public static String locale = "en-US";
public static boolean hdbuttons = false;
public static boolean hdstart = false;
public static boolean isPortraitMode = false;
public static boolean gameInProgress = false;
public static boolean disposeTextures = false;
public static int cacheSize = 400;
public static int totalDeviceRAM = 0;
public static int androidVersion = 0;
public static boolean autoCache = false;
public static int lastButtonIndex = 0;
public static String CJK_Font = "";
public static Forge app;
private static Clipboard clipboard;
private static IDeviceAdapter deviceAdapter;
private static FrameRate frameRate;
private static FScreen currentScreen;
private static SplashScreen splashScreen;
private static Forge.KeyInputAdapter keyInputAdapter;
private static boolean exited;
private static boolean textureFiltering = false;
private static boolean destroyThis = false;
public StartAdventure() {
super();
Forge.isTabletDevice = true;
Forge.isPortraitMode = false;
Forge.hdbuttons = true;
Forge.hdstart = true;
String path= Files.exists(Paths.get("./res"))?"./":"../forge-gui/";
app = (Forge) Forge.getApp(new Lwjgl3Clipboard(), new DesktopAdapter(""), path, true, false, 0, true, 0, "", "");
clipboard = new Lwjgl3Clipboard();
GuiBase.setUsingAppDirectory(false); //obb directory on android uses the package name as entrypoint
GuiBase.setInterface(new GuiMobile(path));
GuiBase.enablePropertyConfig(true);
isPortraitMode = true;
totalDeviceRAM = 0;
GuiBase.setDeviceInfo("", "", 0, 0);
}
@Override
public void render() {
if (splashScreen != null) {
Gdx.gl.glClearColor(1, 0, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear the screen.
getGraphics().begin(getCurrentWidth(), getCurrentHeight());
splashScreen.setSize(getCurrentWidth(), getCurrentHeight());
splashScreen.screenPos.setSize(getCurrentWidth(), getCurrentHeight());
if (splashScreen.getRotate180()) {
getGraphics().startRotateTransform(getCurrentWidth() / 2f, getCurrentHeight() / 2f, 180);
}
splashScreen.draw(getGraphics());
if (splashScreen.getRotate180()) {
getGraphics().endTransform();
}
getGraphics().end();
} else {
super.render();
}
}
@Override
public void resize(int width, int height) {
super.resize(width, height);
if (splashScreen != null)
splashScreen.setSize(width, height);
}
@Override
public void create() {
//install our error handler
ExceptionHandler.registerErrorHandling();
splashScreen = new SplashScreen();
frameRate = new FrameRate();
/*
Set CatchBackKey here and exit the app when you hit the
back button while the textures,fonts,etc are still loading,
to prevent rendering issue when you try to restart
the app again (seems it doesnt dispose correctly...?!?)
*/
Gdx.input.setCatchKey(Input.Keys.BACK, true);
destroyThis = true; //Prevent back()
ForgePreferences prefs = SettingsScene.Preference = new ForgePreferences();
String skinName;
if (FileUtil.doesFileExist(ForgeConstants.MAIN_PREFS_FILE)) {
skinName = prefs.getPref(ForgePreferences.FPref.UI_SKIN);
} else {
skinName = "default"; //use default skin if preferences file doesn't exist yet
}
FSkin.loadLight(skinName, splashScreen,Config.instance().getFile("skin"));
textureFiltering = prefs.getPrefBoolean(ForgePreferences.FPref.UI_LIBGDX_TEXTURE_FILTERING);
showFPS = prefs.getPrefBoolean(ForgePreferences.FPref.UI_SHOW_FPS);
altPlayerLayout = prefs.getPrefBoolean(ForgePreferences.FPref.UI_ALT_PLAYERINFOLAYOUT);
altZoneTabs = prefs.getPrefBoolean(ForgePreferences.FPref.UI_ALT_PLAYERZONETABS);
enableUIMask = prefs.getPref(ForgePreferences.FPref.UI_ENABLE_BORDER_MASKING);
if (prefs.getPref(ForgePreferences.FPref.UI_ENABLE_BORDER_MASKING).equals("true")) //override old settings if not updated
enableUIMask = "Full";
else if (prefs.getPref(ForgePreferences.FPref.UI_ENABLE_BORDER_MASKING).equals("false"))
enableUIMask = "Off";
enablePreloadExtendedArt = prefs.getPrefBoolean(ForgePreferences.FPref.UI_ENABLE_PRELOAD_EXTENDED_ART);
locale = prefs.getPref(ForgePreferences.FPref.UI_LANGUAGE);
autoCache = prefs.getPrefBoolean(ForgePreferences.FPref.UI_AUTO_CACHE_SIZE);
disposeTextures = prefs.getPrefBoolean(ForgePreferences.FPref.UI_ENABLE_DISPOSE_TEXTURES);
CJK_Font = prefs.getPref(ForgePreferences.FPref.UI_CJK_FONT);
if (autoCache) {
//increase cacheSize for devices with RAM more than 5GB, default is 400. Some phones have more than 10GB RAM (Mi 10, OnePlus 8, S20, etc..)
if (totalDeviceRAM > 5000) //devices with more than 10GB RAM will have 800 Cache size, 600 Cache size for morethan 5GB RAM
cacheSize = totalDeviceRAM > 10000 ? 800 : 600;
}
//init cache
ImageCache.initCache(cacheSize);
final Localizer localizer = Localizer.getInstance();
//load model on background thread (using progress bar to report progress)
super.create();
FThreads.invokeInBackgroundThread(new Runnable() {
@Override
public void run() {
//see if app or assets need updating
AssetsDownloader.checkForUpdates(splashScreen);
if (exited) {
return;
} //don't continue if user chose to exit or couldn't download required assets
FModel.initialize(splashScreen.getProgressBar(), null);
splashScreen.getProgressBar().setDescription(localizer.getMessage("lblLoadingFonts"));
FSkinFont.preloadAll(locale);
splashScreen.getProgressBar().setDescription(localizer.getMessage("lblLoadingCardTranslations"));
CardTranslation.preloadTranslation(locale, ForgeConstants.LANG_DIR);
splashScreen.getProgressBar().setDescription(localizer.getMessage("lblFinishingStartup"));
//add reminder to preload
if (enablePreloadExtendedArt) {
if (autoCache)
splashScreen.getProgressBar().setDescription(localizer.getMessage("lblPreloadExtendedArt") + "\nDetected RAM: " + totalDeviceRAM + "MB. Cache size: " + cacheSize);
else
splashScreen.getProgressBar().setDescription(localizer.getMessage("lblPreloadExtendedArt"));
} else {
if (autoCache)
splashScreen.getProgressBar().setDescription(localizer.getMessage("lblFinishingStartup") + "\nDetected RAM: " + totalDeviceRAM + "MB. Cache size: " + cacheSize);
else
splashScreen.getProgressBar().setDescription(localizer.getMessage("lblFinishingStartup"));
}
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
FSkin.loadFull(splashScreen);
SoundSystem.instance.setBackgroundMusic(MusicPlaylist.MENUS); //start background music
destroyThis = false; //Allow back()
Gdx.input.setCatchKey(Input.Keys.MENU, true);
//openHomeScreen(-1); //default for startup
splashScreen = null;
//adjust height modifier
//update landscape mode preference if it doesn't match what the app loaded as
if (!FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_LANDSCAPE_MODE)) {
FModel.getPreferences().setPref(ForgePreferences.FPref.UI_LANDSCAPE_MODE, true);
FModel.getPreferences().save();
}
resLoaded();
if (!enablePreloadExtendedArt)
return;
List<String> borderlessCardlistkeys = FileUtil.readFile(ForgeConstants.BORDERLESS_CARD_LIST_FILE);
if (borderlessCardlistkeys.isEmpty())
return;
List<String> filteredkeys = new ArrayList<>();
for (String cardname : borderlessCardlistkeys) {
File image = new File(ForgeConstants.CACHE_CARD_PICS_DIR + ForgeConstants.PATH_SEPARATOR + cardname + ".jpg");
if (image.exists())
filteredkeys.add(cardname);
}
if (!filteredkeys.isEmpty())
ImageCache.preloadCache(filteredkeys);
/* call preloadExtendedArt here, if we put it above we will *
* get error: No OpenGL context found in the current thread. */
}
});
}
});
}
}
/**
* Main entry point
*/
public class Main {
public static void main(String[] args) {
Sentry.init();
SentryClient sentryClient = Sentry.getStoredClient();
sentryClient.setRelease(BuildInfo.getVersionString());
sentryClient.setEnvironment(System.getProperty("os.name"));
sentryClient.addTag("Java Version", System.getProperty("java.version"));
// HACK - temporary solution to "Comparison method violates it's general contract!" crash
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
//Turn off the Java 2D system's use of Direct3D to improve rendering speed (particularly when Full Screen)
System.setProperty("sun.java2d.d3d", "false");
Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
config.setResizable(false);
StartAdventure start=new StartAdventure();
if (Config.instance().getSettingData().fullScreen)
{
config.setFullscreenMode(Lwjgl3ApplicationConfiguration.getDisplayMode());
} else {
config.setWindowedMode(Config.instance().getSettingData().width, Config.instance().getSettingData().height);
}
config.setWindowIcon(Config.instance().getFilePath("forge-adventure.png"));
new Lwjgl3Application(start, config);
}
}

View File

@@ -0,0 +1,239 @@
package forge.adventure.character;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectSet;
import forge.adventure.stage.SpriteGroup;
import forge.adventure.util.Config;
import java.util.HashMap;
/**
* CharacterSprite base class for animated sprites on the map
*/
public class CharacterSprite extends MapActor {
private final HashMap<AnimationTypes, HashMap<AnimationDirections, Animation<TextureRegion>>> animations = new HashMap<>();
float timer;
private Animation<TextureRegion> currentAnimation = null;
private AnimationTypes currentAnimationType = AnimationTypes.Idle;
private AnimationDirections currentAnimationDir = AnimationDirections.None;
private Sprite avatar;
public CharacterSprite(String path) {
collisionHeight=0.4f;
load(path);
}
protected void load(String path) {
TextureAtlas atlas = Config.instance().getAtlas(path);
for (Texture texture : new ObjectSet.ObjectSetIterator<>( atlas.getTextures()))
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
animations.clear();
for (AnimationTypes stand : AnimationTypes.values()) {
if (stand == AnimationTypes.Avatar) {
avatar = atlas.createSprite(stand.toString());
continue;
}
HashMap<AnimationDirections, Animation<TextureRegion>> dirs = new HashMap<>();
for (AnimationDirections dir : AnimationDirections.values()) {
Array<Sprite> anim;
if (dir == AnimationDirections.None)
anim = atlas.createSprites(stand.toString());
else
anim = atlas.createSprites(stand.toString() + dir.toString());
if (anim.size != 0) {
dirs.put(dir, new Animation<>(0.2f, anim));
}
}
animations.put(stand, dirs);
}
for (AnimationTypes stand : AnimationTypes.values()) {
if (stand == AnimationTypes.Avatar) {
continue;
}
HashMap<AnimationDirections, Animation<TextureRegion>> dirs = animations.get(stand);
if (!dirs.containsKey(AnimationDirections.None) && dirs.containsKey(AnimationDirections.Right)) {
dirs.put(AnimationDirections.None, (dirs.get(AnimationDirections.Right)));
}
if (!dirs.containsKey(AnimationDirections.Right) && dirs.containsKey(AnimationDirections.None)) {
dirs.put(AnimationDirections.Right, (dirs.get(AnimationDirections.None)));
}
if (!dirs.containsKey(AnimationDirections.Left) && dirs.containsKey(AnimationDirections.Right)) {
dirs.put(AnimationDirections.Left, FlipAnimation(dirs.get(AnimationDirections.Right)));
}
if (dirs.containsKey(AnimationDirections.Left) && !dirs.containsKey(AnimationDirections.Right)) {
dirs.put(AnimationDirections.Right, FlipAnimation(dirs.get(AnimationDirections.Left)));
}
if (!dirs.containsKey(AnimationDirections.LeftUp) && dirs.containsKey(AnimationDirections.Left)) {
dirs.put(AnimationDirections.LeftUp, dirs.get(AnimationDirections.Left));
}
if (!dirs.containsKey(AnimationDirections.LeftDown) && dirs.containsKey(AnimationDirections.Left)) {
dirs.put(AnimationDirections.LeftDown, dirs.get(AnimationDirections.Left));
}
if (!dirs.containsKey(AnimationDirections.RightDown) && dirs.containsKey(AnimationDirections.Right)) {
dirs.put(AnimationDirections.RightDown, dirs.get(AnimationDirections.Right));
}
if (!dirs.containsKey(AnimationDirections.RightUp) && dirs.containsKey(AnimationDirections.Right)) {
dirs.put(AnimationDirections.RightUp, dirs.get(AnimationDirections.Right));
}
if (!dirs.containsKey(AnimationDirections.Up) && dirs.containsKey(AnimationDirections.Right)) {
dirs.put(AnimationDirections.Up, dirs.get(AnimationDirections.Right));
}
if (!dirs.containsKey(AnimationDirections.Down) && dirs.containsKey(AnimationDirections.Left)) {
dirs.put(AnimationDirections.Down, dirs.get(AnimationDirections.Left));
}
}
setAnimation(AnimationTypes.Idle);
setDirection(AnimationDirections.Right);
}
static public Animation<TextureRegion> FlipAnimation(Animation<TextureRegion> anim) {
TextureRegion[] texReg = anim.getKeyFrames();
Array<TextureRegion> newReg = new Array<>();
for (TextureRegion reg : texReg) {
TextureRegion cpy = new TextureRegion(reg);
cpy.flip(true, false);
newReg.add(cpy);
}
return new Animation<>(anim.getFrameDuration(), newReg);
}
public void setAnimation(AnimationTypes type) {
if (currentAnimationType != type) {
currentAnimationType = type;
updateAnimation();
}
}
private void updateAnimation() {
AnimationTypes aniType = currentAnimationType;
AnimationDirections aniDir = currentAnimationDir;
if (!animations.containsKey(aniType)) {
aniType = AnimationTypes.Idle;
}
if (!animations.containsKey(aniType)) {
return;
}
HashMap<AnimationDirections, Animation<TextureRegion>> dirs = animations.get(aniType);
if (!dirs.containsKey(aniDir)) {
aniDir = AnimationDirections.Right;
}
if (!dirs.containsKey(aniDir)) {
return;
}
currentAnimation = dirs.get(aniDir);
}
public void setDirection(AnimationDirections dir) {
if (currentAnimationDir != dir) {
currentAnimationDir = dir;
updateAnimation();
}
}
@Override
protected void positionChanged() {
Actor parent = getParent();
if (parent instanceof SpriteGroup) {
((SpriteGroup) parent).UpdateActorZ(this);
}
super.positionChanged();
}
@Override
public void moveBy(float x, float y) {
super.moveBy(x, y);
if (x == 0 && y == 0) {
return;
}
Vector2 vec = new Vector2(x, y);
float degree = vec.angleDeg();
setAnimation(AnimationTypes.Walk);
if (degree < 22.5)
setDirection(AnimationDirections.Right);
else if (degree < 22.5 + 45)
setDirection(AnimationDirections.RightUp);
else if (degree < 22.5 + 45 * 2)
setDirection(AnimationDirections.Up);
else if (degree < 22.5 + 45 * 3)
setDirection(AnimationDirections.LeftUp);
else if (degree < 22.5 + 45 * 4)
setDirection(AnimationDirections.Left);
else if (degree < 22.5 + 45 * 5)
setDirection(AnimationDirections.LeftDown);
else if (degree < 22.5 + 45 * 6)
setDirection(AnimationDirections.Down);
else if (degree < 22.5 + 45 * 7)
setDirection(AnimationDirections.RightDown);
else
setDirection(AnimationDirections.Right);
}
public Vector2 pos() {
return new Vector2(getX(), getY());
}
@Override
public void act(float delta) {
timer += delta;
super.act(delta);
}
@Override
public void draw(Batch batch, float parentAlpha) {
if (currentAnimation == null)
return;
TextureRegion currentFrame = currentAnimation.getKeyFrame(timer, true);
setHeight(currentFrame.getRegionHeight());
setWidth(currentFrame.getRegionWidth());
batch.draw(currentFrame, getX(), getY());
super.draw(batch,parentAlpha);
//batch.draw(getDebugTexture(),getX(),getY());
}
public Sprite getAvatar() {
return avatar;
}
public enum AnimationTypes {
Idle,
Walk,
Death,
Attack,
Hit,
Avatar
}
public enum AnimationDirections {
None,
Right,
RightDown,
Down,
LeftDown,
Left,
LeftUp,
Up,
RightUp
}
}

View File

@@ -0,0 +1,58 @@
package forge.adventure.character;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.utils.Array;
import forge.adventure.data.EnemyData;
import forge.adventure.data.RewardData;
import forge.adventure.util.Current;
import forge.adventure.util.Reward;
/**
* EnemySprite
* Character sprite that represents an Enemy
*/
public class EnemySprite extends CharacterSprite {
EnemyData data;
private int id;
public EnemySprite(EnemyData enemyData) {
super(enemyData.sprite);
data = enemyData;
}
public EnemySprite(int id, EnemyData enemyData) {
this(enemyData);
this.id = id;
}
public void moveTo(Actor other, float delta) {
Vector2 diff = new Vector2(other.getX(), other.getY()).sub(pos());
diff.setLength(data.speed*delta);
moveBy(diff.x, diff.y);
}
public EnemyData getData() {
return data;
}
public Array<Reward> getRewards() {
Array<Reward> ret=new Array<Reward>();
if(data.rewards==null)
return ret;
for(RewardData rdata:data.rewards)
{
ret.addAll(rdata.generate(false,Current.latestDeck()!=null? Current.latestDeck().getMain().toFlatList():null));
}
return ret;
}
public int getId() {
return id;
}
}

View File

@@ -0,0 +1,68 @@
package forge.adventure.character;
import forge.adventure.scene.SceneType;
import forge.adventure.scene.TileMapScene;
import forge.adventure.stage.MapStage;
/**
* EntryActor
* Used to teleport the player in and out of the map
*/
public class EntryActor extends MapActor{
private final MapStage stage;
private final int id;
String targetMap;
public EntryActor(MapStage stage,String sourceMap, int id,String targetMap,float x,float y,float w,float h,String direction)
{
this.stage = stage;
this.id = id;
this.targetMap = targetMap;
if((targetMap==null||targetMap.isEmpty()&&sourceMap.isEmpty())||//if target is null and "from world"
!sourceMap.isEmpty()&&targetMap.equals(sourceMap)) //or if source is this target
{
switch(direction)
{
case "up":
stage.GetPlayer().setPosition(x,y+h);
break;
case "down":
stage.GetPlayer().setPosition(x,y-stage.GetPlayer().getHeight());
break;
case "right":
stage.GetPlayer().setPosition(x-stage.GetPlayer().getWidth(),y);
break;
case "left":
stage.GetPlayer().setPosition(x+w,y);
break;
}
}
}
public MapStage getMapStage()
{
return stage;
}
@Override
public void onPlayerCollide()
{
if(targetMap==null||targetMap.isEmpty())
{
stage.exit();
}
else
{
((TileMapScene)SceneType.TileMapScene.instance).loadNext(targetMap);
}
}
public int getObjectID() {
return id;
}
}

View File

@@ -0,0 +1,96 @@
package forge.adventure.character;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.Actor;
/**
* Map Actor base class for Actors on the map
* implements collision detection.
*/
public class MapActor extends Actor {
Texture debugTexture;
float collisionHeight=1.0f;
private Texture getDebugTexture() {
if (debugTexture == null) {
Pixmap pixmap = new Pixmap((int) getWidth(), (int) getHeight(), Pixmap.Format.RGBA8888);
pixmap.setColor(1.0f,0,0,0.5f);
pixmap.fillRectangle(0, (int) getHeight()- (int)boundingRect.getHeight(), (int) boundingRect.getWidth(), (int) boundingRect.getHeight());
debugTexture = new Texture(pixmap);
pixmap.dispose();
}
return debugTexture;
}
Rectangle boundingRect;
boolean isCollidingWithPlayer=false;
protected void onPlayerCollide()
{
}
boolean boundDebug=false;
public void setBoundDebug(boolean debug)
{
boundDebug=debug;
}
@Override
public void draw(Batch batch, float alpha) {
if(boundDebug)
batch.draw(getDebugTexture(),getX(),getY());
}
@Override
protected void positionChanged() {
updateBoundingRect();
super.positionChanged();
}
@Override
protected void sizeChanged() {
super.sizeChanged();
updateBoundingRect();
}
void updateBoundingRect() {
boundingRect = new Rectangle(getX(), getY(), getWidth(), getHeight()*collisionHeight);
}
public Rectangle boundingRect() {
return boundingRect;
}
public boolean collideWithPlayer(PlayerSprite other) {
boolean newIsColliding= collideWith(other);
if(newIsColliding)
{
if(!isCollidingWithPlayer)
onPlayerCollide();
isCollidingWithPlayer=true;
}
else
{
isCollidingWithPlayer=false;
}
return isCollidingWithPlayer;
}
public boolean collideWith(Rectangle other) {
return boundingRect().overlaps(other);
}
public boolean collideWith(MapActor other) {
return collideWith(other.boundingRect());
}
public boolean collideWith(Actor other) {
return boundingRect.x < other.getX() + other.getWidth() && boundingRect.x + boundingRect.width > other.getX() && boundingRect.y < other.getY() + other.getHeight() && boundingRect.y + boundingRect.height > other.getY();
}
}

View File

@@ -0,0 +1,21 @@
package forge.adventure.character;
/**
* Designed to add anonymous class for a single action on collision
*/
public class OnCollide extends MapActor {
Runnable onCollide;
public OnCollide(Runnable func) {
onCollide = func;
}
@Override
protected void onPlayerCollide() {
try {
onCollide.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,77 @@
package forge.adventure.character;
import com.badlogic.gdx.math.Vector2;
import forge.adventure.stage.GameStage;
import forge.adventure.util.Config;
import forge.adventure.util.Current;
import forge.adventure.world.AdventurePlayer;
/**
* Class that will represent the player sprite on the map
*/
public class PlayerSprite extends CharacterSprite {
private final float playerSpeed;
private final Vector2 direction = Vector2.Zero.cpy();
private float playerSpeedModifier = 1f;
GameStage gameStage;
public PlayerSprite(GameStage gameStage) {
super(AdventurePlayer.current().spriteName());
this.gameStage=gameStage;
setOriginX(getWidth() / 2);
Current.player().onPlayerChanged(()->updatePlayer());
playerSpeed=Config.instance().getConfigData().playerBaseSpeed;
}
private void updatePlayer() {
load(AdventurePlayer.current().spriteName());
}
public void LoadPos() {
setPosition(AdventurePlayer.current().getWorldPosX(), AdventurePlayer.current().getWorldPosY());
}
public void storePos() {
AdventurePlayer.current().setWorldPosX(getX());
AdventurePlayer.current().setWorldPosY(getY());
}
public Vector2 getMovementDirection() {
return direction;
}
public void setMovementDirection(final Vector2 dir) {
direction.set(dir);
}
public void setMoveModifier(float speed) {
playerSpeedModifier = speed;
}
@Override
public void act(float delta) {
super.act(delta);
direction.setLength(playerSpeed * delta * playerSpeedModifier);
if(!direction.isZero())
{
gameStage.prepareCollision(pos(),direction,boundingRect);
direction.set(gameStage.adjustMovement(direction,boundingRect));
moveBy(direction.x, direction.y);
}
}
public boolean isMoving() {
return !direction.isZero();
}
public void stop() {
direction.setZero();
setAnimation(AnimationTypes.Idle);
}
public void setPosition(Vector2 oldPosition) {
setPosition(oldPosition.x,oldPosition.y);
}
}

View File

@@ -0,0 +1,43 @@
package forge.adventure.character;
import com.badlogic.gdx.utils.Array;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.scene.RewardScene;
import forge.adventure.scene.SceneType;
import forge.adventure.stage.MapStage;
import forge.adventure.util.Reward;
/**
* Map actor that will open the Shop on collision
*/
public class ShopActor extends MapActor{
private final MapStage stage;
private final int id;
Array<Reward> rewardData;
public ShopActor(MapStage stage, int id, Array<Reward> rewardData)
{
this.stage = stage;
this.id = id;
this.rewardData = rewardData;
}
public MapStage getMapStage()
{
return stage;
}
@Override
public void onPlayerCollide()
{
stage.GetPlayer().stop();
((RewardScene) SceneType.RewardScene.instance).loadRewards(rewardData, RewardScene.Type.Shop,this);
AdventureApplicationAdapter.instance.switchScene(SceneType.RewardScene.instance);
}
public int getObjectID() {
return id;
}
}

View File

@@ -0,0 +1,25 @@
package forge.adventure.character;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
/**
* Class to add sprites to a map
*/
public class TextureSprite extends MapActor{
private final TextureRegion region;
public TextureSprite(TextureRegion region)
{
this.region = region;
setWidth(region.getRegionWidth());
setHeight(region.getRegionHeight());
}
@Override
public void draw (Batch batch, float parentAlpha) {
batch.draw(region,getX(),getY(),getWidth(),getHeight());
}
}

View File

@@ -0,0 +1,82 @@
package forge.adventure.data;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.Array;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains the information for the biomes
*/
public class BiomeData implements Serializable {
private final Random rand = new Random();
public float startPointX;
public float startPointY;
public float noiseWeight;
public float distWeight;
public String name;
public String tilesetAtlas;
public String tilesetName;
public BiomeTerrainData[] terrain;
public float width;
public float height;
public String color;
public boolean invertHeight;
public String[] spriteNames;
public List<String> enemies;
public List<String> pointsOfInterest;
private ArrayList<EnemyData> enemyList;
private ArrayList<PointOfInterestData> pointOfInterestList;
public Color GetColor() {
return Color.valueOf(color);
}
public ArrayList<EnemyData> getEnemyList() {
if (enemyList == null) {
enemyList = new ArrayList<EnemyData>();
if (enemies == null)
return enemyList;
for (EnemyData data : new Array.ArrayIterator<>(WorldData.getAllEnemies())) {
if (enemies.contains(data.name)) {
enemyList.add(data);
}
}
}
return enemyList;
}
public ArrayList<PointOfInterestData> getPointsOfInterest() {
if (pointOfInterestList == null) {
pointOfInterestList = new ArrayList<PointOfInterestData>();
if(pointsOfInterest==null)
return pointOfInterestList;
Array<PointOfInterestData> allTowns = PointOfInterestData.getAllPointOfInterest();
for (PointOfInterestData data : new Array.ArrayIterator<>(allTowns)) {
if (pointsOfInterest.contains(data.name)) {
pointOfInterestList.add(data);
}
}
}
return pointOfInterestList;
}
public EnemyData getEnemy(float difficultyFactor) {
EnemyData bestData=null;
float biggestNumber=0;
for (EnemyData data : enemyList) {
float newNumber=data.spawnRate *rand.nextFloat()*difficultyFactor;
if (newNumber>biggestNumber) {
biggestNumber=newNumber;
bestData=data;
}
}
return bestData;
}
}

View File

@@ -0,0 +1,21 @@
package forge.adventure.data;
import java.io.Serializable;
/**
* Data class that will be used to read Json configuration files
* BiomeSpriteData
* contains the information for the sprites on the map like trees and rocks
*/
public class BiomeSpriteData implements Serializable {
public String name;
public double startArea;
public double endArea;
public double density;
public double resolution;
public int layer;
public String key() {
return "BiomeSprite&" + name;
}
}

View File

@@ -0,0 +1,19 @@
package forge.adventure.data;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains the information for the terrain distribution
*/
public class BiomeTerrainData {
//sprite name in the biome atlas file
public String spriteName;
//minimum noise value where to place the terrain
public float min;
//maximum noise value where to place the terrain
public float max;
// factor for the noise resolution
public float resolution;
}

View File

@@ -0,0 +1,20 @@
package forge.adventure.data;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains general information about the game
*/
public class ConfigData {
public int screenWidth;
public int screenHeight;
public String skin;
public String font;
public String fontColor;
public int minDeckSize;
public float playerBaseSpeed;
public String[] starterDecks;
public DifficultyData[] difficulties;
public RewardData legalCards;
}

View File

@@ -0,0 +1,15 @@
package forge.adventure.data;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains the information for the difficulties
*/
public class DifficultyData {
public String name="";
public int startingLife=10;
public int staringMoney=10;
public float enemyLifeFactor=1;
public boolean startingDifficulty;
}

View File

@@ -0,0 +1,48 @@
package forge.adventure.data;
import forge.adventure.util.CardUtil;
import forge.deck.Deck;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains the information of enemies
*/
public class EnemyData {
public String name;
public String sprite;
public String deck;
public float spawnRate;
public float difficulty;
public float speed;
public int life;
public RewardData[] rewards;
public EnemyData()
{
}
public EnemyData(EnemyData enemyData) {
name =enemyData.name;
sprite =enemyData.sprite;
deck =enemyData.deck;
spawnRate =enemyData.spawnRate;
difficulty =enemyData.difficulty ;
speed =enemyData.speed;
life =enemyData.life;
if(enemyData.rewards==null)
{
rewards=null;
}
else
{
rewards =new RewardData[enemyData.rewards.length];
for(int i=0;i<rewards.length;i++)
rewards[i]=new RewardData(enemyData.rewards[i]);
}
}
public Deck generateDeck() {
return CardUtil.getDeck(deck);
}
}

View File

@@ -0,0 +1,17 @@
package forge.adventure.data;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains the information for a generated deck
*
* if the template is null then it will use just the reward information of mainDeck and sideBoard
*/
public class GeneratedDeckData {
public String name;
public GeneratedDeckTemplateData template;
public RewardData[] mainDeck;
public RewardData[] sideBoard;
}

View File

@@ -0,0 +1,15 @@
package forge.adventure.data;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains the information for the generated deck
*/
public class GeneratedDeckTemplateData {
public String[] colors;
public int count;
public float rares;
public String tribe;
public float tribeSynergyCards=0.6f;
public float tribeCards=1.0f;
}

View File

@@ -0,0 +1,14 @@
package forge.adventure.data;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains the information possible hero sprite
*/
public class HeroData {
public String name;
public String female;
public String male;
public String femaleAvatar;
public String maleAvatar;
}

View File

@@ -0,0 +1,73 @@
package forge.adventure.data;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import forge.adventure.util.Config;
import forge.adventure.util.Paths;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains the a list of all heroes
*/
public class HeroListData {
static private HeroListData instance;
public HeroData[] heroes;
public String avatar;
private TextureAtlas avatarSprites;
static private HeroListData read() {
Json json = new Json();
FileHandle handle = Config.instance().getFile(Paths.HEROES);
if (handle.exists()) {
instance = json.fromJson(HeroListData.class, handle);
instance.avatarSprites = Config.instance().getAtlas(instance.avatar);
instance.avatarSprites.getTextures().first().setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
}
return instance;
}
static public String getHero(int raceIndex, boolean female) {
if (instance == null)
instance = read();
HeroData data = instance.heroes[raceIndex];
if (female)
return data.female;
return data.male;
}
public static TextureRegion getAvatar(int heroRace, boolean isFemale, int avatarIndex) {
if (instance == null)
instance = read();
HeroData data = instance.heroes[heroRace];
Array<Sprite> sprites;
if (isFemale)
sprites = instance.avatarSprites.createSprites(data.femaleAvatar);
else
sprites = instance.avatarSprites.createSprites(data.maleAvatar);
avatarIndex %= sprites.size;
if (avatarIndex < 0) {
avatarIndex += sprites.size;
}
return sprites.get(avatarIndex);
}
public static Array<String> getRaces() {
if (instance == null)
instance = read();
Array<String> ret = new Array<>();
for (HeroData hero : instance.heroes) {
ret.add(hero.name);
}
return ret;
}
}

View File

@@ -0,0 +1,47 @@
package forge.adventure.data;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import forge.adventure.util.Config;
import forge.adventure.util.Paths;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains the information for the point of interests like towns and dungeons
*/
public class PointOfInterestData {
public String name;
public String type;
public int count;
public String spriteAtlas;
public String sprite;
public String map;
public float radiusFactor;
private static Array<PointOfInterestData> pointOfInterestList;
public static Array<PointOfInterestData> getAllPointOfInterest() {
if (pointOfInterestList == null) {
Json json = new Json();
FileHandle handle = Config.instance().getFile(Paths.POINTS_OF_INTEREST);
if (handle.exists()) {
Array readJson = json.fromJson(Array.class, PointOfInterestData.class, handle);
pointOfInterestList = readJson;
}
}
return pointOfInterestList;
}
public static PointOfInterestData getPointOfInterest(String name) {
for(PointOfInterestData data: new Array.ArrayIterator<>(getAllPointOfInterest()))
{
if(data.name.equals(name))
return data;
}
return null;
}
}

View File

@@ -0,0 +1,157 @@
package forge.adventure.data;
import com.badlogic.gdx.utils.Array;
import com.google.common.collect.Iterables;
import forge.StaticData;
import forge.adventure.util.CardUtil;
import forge.adventure.util.Config;
import forge.adventure.util.Reward;
import forge.adventure.world.WorldSave;
import forge.item.PaperCard;
import forge.model.FModel;
import java.util.ArrayList;
import java.util.List;
/**
* Data class that will be used to read Json configuration files
* BiomeData
* contains the information for a "reward"
* that can be a random card, gold or items.
* Also used for deck generation and shops
*/
public class RewardData {
public String type;
public float probability;
public int count;
public int addMaxCount;
public String cardName;
public String itemName;
public String[] editions;
public String[] colors;
public String[] rarity;
public String[] subTypes;
public String[] cardTypes;
public String[] superTypes;
public int[] manaCosts;
public String[] keyWords;
public String colorType;
public String cardText;
public boolean matchAllSubTypes;
public RewardData()
{
}
public RewardData(RewardData rewardData) {
type =rewardData.type;
probability =rewardData.probability;
count =rewardData.count;
addMaxCount =rewardData.addMaxCount;
cardName =rewardData.cardName;
itemName =rewardData.itemName;
editions =rewardData.editions==null?null:rewardData.editions.clone();
colors =rewardData.colors==null?null:rewardData.colors.clone();
rarity =rewardData.rarity==null?null:rewardData.rarity.clone();
subTypes =rewardData.subTypes==null?null:rewardData.subTypes.clone();
cardTypes =rewardData.cardTypes==null?null:rewardData.cardTypes.clone();
superTypes =rewardData.superTypes==null?null:rewardData.superTypes.clone();
manaCosts =rewardData.manaCosts==null?null:rewardData.manaCosts.clone();
keyWords =rewardData.keyWords==null?null:rewardData.keyWords.clone();
colorType =rewardData.colorType;
cardText =rewardData.cardText;
matchAllSubTypes =rewardData.matchAllSubTypes;
}
private static Iterable<PaperCard> allCards;
private static Iterable<PaperCard> allEnemyCards;
public Array<Reward> generate(boolean isForEnemy)
{
return generate(isForEnemy,null);
}
public Array<Reward> generate(boolean isForEnemy,Iterable<PaperCard> cards)
{
if(allCards==null)
{
RewardData legals=Config.instance().getConfigData().legalCards;
if(legals==null)
{
allCards = FModel.getMagicDb().getCommonCards().getUniqueCardsNoAlt();
}
else
{
allCards = Iterables.filter(FModel.getMagicDb().getCommonCards().getUniqueCardsNoAlt(), new CardUtil.CardPredicate(legals, true));
}
allEnemyCards=Iterables.filter(allCards, input -> {
if(input==null)return false;
return !input.getRules().getAiHints().getRemAIDecks();
});
}
Array<Reward> ret=new Array<>();
if(probability==0|| WorldSave.getCurrentSave().getWorld().getRandom().nextFloat()<=probability)
{
if(type==null||type.isEmpty())
type="randomCard";
int addedCount=(int)((float)(addMaxCount)* WorldSave.getCurrentSave().getWorld().getRandom().nextFloat());
switch(type)
{
case "card":
case "randomCard":
if(cardName!=null&&!cardName.isEmpty())
{
for(int i=0;i<count+addedCount;i++)
{
ret.add(new Reward(StaticData.instance().getCommonCards().getCard(cardName)));
}
}
else
{
for(PaperCard card:CardUtil.generateCards(isForEnemy?allEnemyCards:allCards,this, count+addedCount))
{
ret.add(new Reward(card));
}
}
break;
case "deckCard":
if(cards==null)return ret;
for(PaperCard card: CardUtil.generateCards(cards,this, count+addedCount))
{
ret.add(new Reward(card));
}
break;
case "gold":
ret.add(new Reward(count+addedCount));
break;
case "life":
ret.add(new Reward(Reward.Type.Life, count+addedCount));
break;
}
}
return ret;
}
static public List<PaperCard> generateAllCards(Iterable<RewardData> dataList, boolean isForEnemy)
{
return rewardsToCards(generateAll(dataList, isForEnemy));
}
static public Iterable<Reward> generateAll(Iterable<RewardData> dataList, boolean isForEnemy)
{
Array<Reward> ret=new Array<Reward>();
for (RewardData data:dataList)
ret.addAll(data.generate(isForEnemy));
return ret;
}
static public List<PaperCard> rewardsToCards(Iterable<Reward> dataList)
{
ArrayList<PaperCard> ret=new ArrayList<PaperCard>();
for (Reward data:dataList)
{
ret.add(data.getCard());
}
return ret;
}
}

View File

@@ -0,0 +1,15 @@
package forge.adventure.data;
/**
* Data class that will be used to read Json configuration files
* SettingData
* contains settings outside of the chosen adventure
*/
public class SettingData {
public int width;
public int height;
public String plane;
public boolean fullScreen;
}

View File

@@ -0,0 +1,21 @@
package forge.adventure.data;
import com.badlogic.gdx.utils.Array;
/**
* Data class that will be used to read Json configuration files
* SettingData
* contains data for a Shop on the map
*/
public class ShopData {
public String name;
public String spriteAtlas;
public String sprite;
public Array<RewardData> rewards;
}

View File

@@ -0,0 +1,16 @@
package forge.adventure.data;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.OrderedMap;
/**
* Data class that will be used to read Json configuration files
* UIData
* contains a GUI definition, used for most user interfaces to customize the UI
*/
public class UIData {
public int width;
public int height;
public boolean yDown;
public Array<OrderedMap<String,String>> elements;
}

View File

@@ -0,0 +1,93 @@
package forge.adventure.data;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import forge.adventure.util.Config;
import forge.adventure.util.Paths;
import forge.adventure.world.BiomeSprites;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Data class that will be used to read Json configuration files
* UIData
* contains the definition of the world
*/
public class WorldData implements Serializable {
static Array<EnemyData> allEnemies;
public int width;
public int height;
public float playerStartPosX;
public float playerStartPosY;
public float noiseZoomBiome;
public int tileSize;
public List<String> biomesNames;
public BiomeData roadTileset;
public String biomesSprites;
public float maxRoadDistance;
private BiomeSprites sprites;
private List<BiomeData> biomes;
private static Array<ShopData> shopList;
public static Array<ShopData> getShopList() {
if (shopList == null) {
shopList = new Array<>();
Json json = new Json();
FileHandle handle = Config.instance().getFile(Paths.SHOPS);
if (handle.exists())
{
Array readList = json.fromJson(Array.class, ShopData.class, handle);
shopList = readList;
}
}
return shopList;
}
static public Array<EnemyData> getAllEnemies() {
if (allEnemies == null) {
Json json = new Json();
FileHandle handle = Config.instance().getFile(Paths.ENEMIES);
if (handle.exists())
{
Array readList = json.fromJson(Array.class, EnemyData.class, handle);
allEnemies = readList;
}
}
return allEnemies;
}
public static EnemyData getEnemy(String enemy) {
for(EnemyData data: new Array.ArrayIterator<>(getAllEnemies()))
{
if(data.name.equals(enemy))
return data;
}
return null;
}
public BiomeSprites GetBiomeSprites() {
if (sprites == null) {
Json json = new Json();
sprites = (json.fromJson(BiomeSprites.class, Config.instance().getFile(biomesSprites)));
}
return sprites;
}
public List<BiomeData> GetBiomes() {
if (biomes == null) {
biomes = new ArrayList<BiomeData>();
Json json = new Json();
for (String name : biomesNames) {
biomes.add(json.fromJson(BiomeData.class, Config.instance().getFile(name)));
}
}
return biomes;
}
}

View File

@@ -0,0 +1,32 @@
package forge.adventure.editor;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class DocumentChangeListener implements DocumentListener {
private final Runnable run;
public DocumentChangeListener(Runnable run)
{
this.run = run;
}
@Override
public void insertUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
run.run();
}
}

View File

@@ -0,0 +1,21 @@
package forge.adventure.editor;
import javax.swing.*;
import java.awt.*;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class EditorMainWindow extends JFrame {
JTabbedPane tabs =new JTabbedPane();
public EditorMainWindow()
{
BorderLayout layout=new BorderLayout();
setLayout(layout);
add(tabs);
tabs.addTab("Enemies",new EnemyEditor());
setVisible(true);
setSize(800,600);
}
}

View File

@@ -0,0 +1,95 @@
package forge.adventure.editor;
import forge.adventure.data.EnemyData;
import javax.swing.*;
import java.awt.*;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class EnemyEdit extends JComponent {
EnemyData currentData;
JTextField nameField=new JTextField();
JSpinner lifeFiled= new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1));
JSpinner spawnRate= new JSpinner(new SpinnerNumberModel(0.0, 0., 1, 0.1));
JSpinner difficulty= new JSpinner(new SpinnerNumberModel(0.0, 0., 1, 0.1));
JSpinner speed= new JSpinner(new SpinnerNumberModel(0.0, 0., 100., 1.0));
FilePicker deck=new FilePicker(new String[]{"dck","json"});
FilePicker atlas=new FilePicker(new String[]{"atlas"});
RewardsEditor rewards=new RewardsEditor();
SwingAtlasPreview preview=new SwingAtlasPreview();
private boolean updating=false;
public EnemyEdit()
{
JComponent center=new JComponent() { };
center.setLayout(new GridLayout(8,2));
center.add(new JLabel("Name:")); center.add(nameField);
center.add(new JLabel("Life:")); center.add(lifeFiled);
center.add(new JLabel("Spawn rate:")); center.add(spawnRate);
center.add(new JLabel("Difficulty:")); center.add(difficulty);
center.add(new JLabel("Speed:")); center.add(speed);
center.add(new JLabel("Deck:")); center.add(deck);
center.add(new JLabel("Sprite:")); center.add(atlas);
BorderLayout layout=new BorderLayout();
setLayout(layout);
add(center,BorderLayout.PAGE_START);
add(rewards,BorderLayout.CENTER);
add(preview,BorderLayout.LINE_START);
atlas.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(()->updateEnemy()));
nameField.getDocument().addDocumentListener(new DocumentChangeListener(()->updateEnemy()));
deck.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(()->updateEnemy()));
lifeFiled.addChangeListener(e -> updateEnemy());
speed.addChangeListener(e -> updateEnemy());
difficulty.addChangeListener(e -> updateEnemy());
spawnRate.addChangeListener(e -> updateEnemy());
rewards.addChangeListener(e -> updateEnemy());
lifeFiled.addChangeListener(e -> updateEnemy());
refresh();
}
private void updateEnemy() {
if(currentData==null||updating)
return;
currentData.name=nameField.getText();
currentData.life= (int) lifeFiled.getValue();
currentData.sprite= atlas.getEdit().getText();
currentData.speed= ((Double) speed.getValue()).floatValue();
currentData.spawnRate=((Double) spawnRate.getValue()).floatValue();
currentData.difficulty=((Double) difficulty.getValue()).floatValue();
currentData.deck= deck.getEdit().getText();
currentData.rewards= rewards.getRewards();
preview.setSpritePath(currentData.sprite);
}
public void setCurrentEnemy(EnemyData data)
{
currentData=data;
refresh();
}
private void refresh() {
setEnabled(currentData!=null);
if(currentData==null)
{
return;
}
updating=true;
nameField.setText(currentData.name);
lifeFiled.setValue(currentData.life);
atlas.getEdit().setText(currentData.sprite);
deck.getEdit().setText(currentData.deck);
speed.setValue(new Float(currentData.speed).doubleValue());
spawnRate.setValue(new Float(currentData.spawnRate).doubleValue());
difficulty.setValue(new Float(currentData.difficulty).doubleValue());
rewards.setRewards(currentData.rewards);
preview.setSpritePath(currentData.sprite);
updating=false;
}
}

View File

@@ -0,0 +1,128 @@
package forge.adventure.editor;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonWriter;
import forge.adventure.data.EnemyData;
import forge.adventure.util.Config;
import forge.adventure.util.Paths;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class EnemyEditor extends JComponent {
DefaultListModel<EnemyData> model = new DefaultListModel<>();
JList<EnemyData> list = new JList<>(model);
JToolBar toolBar = new JToolBar("toolbar");
EnemyEdit edit=new EnemyEdit();
public class EnemyDataRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if(!(value instanceof EnemyData))
return label;
EnemyData enemy=(EnemyData) value;
// Get the renderer component from parent class
label.setText(enemy.name);
SwingAtlas atlas=new SwingAtlas(Config.instance().getFile(enemy.sprite));
if(atlas.has("Avatar"))
label.setIcon(atlas.get("Avatar"));
else
{
ImageIcon img=atlas.getAny();
if(img!=null)
label.setIcon(img);
}
return label;
}
}
public void addButton(String name,ActionListener action)
{
JButton newButton=new JButton(name);
newButton.addActionListener(action);
toolBar.add(newButton);
}
public EnemyEditor()
{
list.setCellRenderer(new EnemyDataRenderer());
list.addListSelectionListener(e -> updateEdit());
addButton("add",e->addEnemy());
addButton("remove",e->remove());
addButton("copy",e->copy());
addButton("load",e->load());
addButton("save",e->save());
BorderLayout layout=new BorderLayout();
setLayout(layout);
add(new JScrollPane(list), BorderLayout.LINE_START);
add(toolBar, BorderLayout.PAGE_START);
add(edit,BorderLayout.CENTER);
load();
}
private void copy() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
EnemyData data=new EnemyData(model.get(selected));
model.add(model.size(),data);
}
private void updateEdit() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
edit.setCurrentEnemy(model.get(selected));
}
void save()
{
Array<EnemyData> allEnemies=new Array<>();
for(int i=0;i<model.getSize();i++)
allEnemies.add(model.get(i));
Json json = new Json(JsonWriter.OutputType.json);
FileHandle handle = Config.instance().getFile(Paths.ENEMIES);
handle.writeString(json.prettyPrint(json.toJson(allEnemies,Array.class, EnemyData.class)),false);
}
void load()
{
model.clear();
Array<EnemyData> allEnemies=new Array<>();
Json json = new Json();
FileHandle handle = Config.instance().getFile(Paths.ENEMIES);
if (handle.exists())
{
Array readEnemies=json.fromJson(Array.class, EnemyData.class, handle);
allEnemies = readEnemies;
}
for (int i=0;i<allEnemies.size;i++) {
model.add(i,allEnemies.get(i));
}
}
void addEnemy()
{
EnemyData data=new EnemyData();
data.name="Enemy "+model.getSize();
model.add(model.size(),data);
}
void remove()
{
int selected=list.getSelectedIndex();
if(selected<0)
return;
model.remove(selected);
}
}

View File

@@ -0,0 +1,51 @@
package forge.adventure.editor;
import forge.adventure.util.Config;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.File;
import java.io.IOException;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class FilePicker extends Box {
JTextField edit=new JTextField();
JButton findButton=new JButton(UIManager.getIcon("FileView.directoryIcon"));
private final String[] fileEndings;
public FilePicker(String[] fileEndings) {
super(BoxLayout.X_AXIS);
this.fileEndings = fileEndings;
findButton.addActionListener(e->find());
add(edit);
add(findButton);
}
JTextField getEdit()
{
return edit;
}
private void find() {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File(Config.instance().getFilePath(edit.getText())));
fc.setFileFilter( new FileNameExtensionFilter("Pick File",fileEndings));
fc.setMultiSelectionEnabled(false);
if (fc.showOpenDialog(this) ==
JFileChooser.APPROVE_OPTION) {
File selected = fc.getSelectedFile();
try {
if (selected != null&&selected.getCanonicalPath().startsWith(new File(Config.instance().getFilePath("")).getCanonicalPath())) {
edit.setText(selected.getCanonicalPath().substring(new File(Config.instance().getFilePath("")).getCanonicalPath().length()+1).replace('\\','/'));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,13 @@
package forge.adventure.editor;
import forge.adventure.util.Config;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class Main {
public static void main(String[] args) {
Config.instance();
new EditorMainWindow();
}
}

View File

@@ -0,0 +1,146 @@
package forge.adventure.editor;
import forge.adventure.data.RewardData;
import forge.card.CardType;
import forge.game.keyword.Keyword;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.util.Arrays;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class RewardEdit extends JComponent {
RewardData currentData;
JComboBox typeField =new JComboBox(new String[] { "card", "gold", "life", "deckCard", "item"});
JSpinner probability = new JSpinner(new SpinnerNumberModel(0f, 0, 1, 0.1f));
JSpinner count = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1));
JSpinner addMaxCount = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1));
JTextField cardName =new JTextField();
JTextField itemName =new JTextField();
TextListEdit editions =new TextListEdit();
TextListEdit colors =new TextListEdit(new String[] { "White", "Blue", "Black", "Red", "Green" });
TextListEdit rarity =new TextListEdit(new String[] { "Basic Land", "Common", "Uncommon", "Rare", "Mythic Rare" });
TextListEdit subTypes =new TextListEdit();
TextListEdit cardTypes =new TextListEdit(Arrays.asList(CardType.CoreType.values()).stream().map(CardType.CoreType::toString).toArray(String[]::new));
TextListEdit superTypes =new TextListEdit(Arrays.asList(CardType.Supertype.values()).stream().map(CardType.Supertype::toString).toArray(String[]::new));
TextListEdit manaCosts =new TextListEdit();
TextListEdit keyWords =new TextListEdit(Arrays.asList(Keyword.values()).stream().map(Keyword::toString).toArray(String[]::new));
JComboBox colorType =new JComboBox(new String[] { "Any", "Colorless", "MultiColor", "MonoColor"});
JTextField cardText =new JTextField();
private boolean updating=false;
public RewardEdit()
{
setLayout(new GridLayout(16,2));
add(new JLabel("Type:")); add(typeField);
add(new JLabel("probability:")); add(probability);
add(new JLabel("count:")); add(count);
add(new JLabel("addMaxCount:")); add(addMaxCount);
add(new JLabel("cardName:")); add(cardName);
add(new JLabel("itemName:")); add(itemName);
add(new JLabel("editions:")); add(editions);
add(new JLabel("colors:")); add(colors);
add(new JLabel("rarity:")); add(rarity);
add(new JLabel("subTypes:")); add(subTypes);
add(new JLabel("cardTypes:")); add(cardTypes);
add(new JLabel("superTypes:")); add(superTypes);
add(new JLabel("manaCosts:")); add(manaCosts);
add(new JLabel("keyWords:")); add(keyWords);
add(new JLabel("colorType:")); add(colorType);
add(new JLabel("cardText:")); add(cardText);
typeField.addActionListener(((e)->updateReward()));
probability.addChangeListener(e->updateReward());
count.addChangeListener(e->updateReward());
addMaxCount.addChangeListener(e->updateReward());
cardName.getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
itemName.getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
editions.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
colors.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
rarity.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
subTypes.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
cardTypes.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
superTypes.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
manaCosts.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
keyWords.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
colorType.addActionListener(((e)->updateReward()));
cardText.getDocument().addDocumentListener(new DocumentChangeListener(()->updateReward()));
}
private void updateReward() {
if(currentData==null||updating)
return;
currentData.type=typeField.getSelectedItem()==null?null:typeField.getSelectedItem().toString();
currentData.probability=((Double)probability.getValue()).floatValue();
currentData.count= (int) count.getValue();
currentData.addMaxCount= (int) addMaxCount.getValue();
currentData.cardName = cardName.getText().isEmpty()?null:cardName.getText();
currentData.itemName = itemName.getText().isEmpty()?null:itemName.getText();
currentData.editions = editions.getList();
currentData.colors = colors.getList();
currentData.rarity = rarity.getList();
currentData.subTypes = subTypes.getList();
currentData.cardTypes = cardTypes.getList();
currentData.superTypes = superTypes.getList();
currentData.manaCosts = manaCosts.getListAsInt();
currentData.keyWords = keyWords.getList();
currentData.colorType=colorType.getSelectedItem()==null?null:colorType.getSelectedItem().toString();
currentData.cardText = cardText.getText().isEmpty()?null:cardText.getText();
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
if (listeners != null && listeners.length > 0) {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
}
public void addChangeListener(ChangeListener l) {
listenerList.add(ChangeListener.class, l);
}
public void setCurrentReward(RewardData data)
{
currentData=data;
refresh();
}
private void refresh() {
setEnabled(currentData!=null);
if(currentData==null)
{
return;
}
updating=true;
typeField.setSelectedItem(currentData.type);
probability.setValue(new Double(currentData.probability));
count.setValue(currentData.count);
addMaxCount.setValue(currentData.addMaxCount);
cardName.setText(currentData.cardName);
itemName.setText(currentData.itemName);
editions.setText(currentData.editions);
colors.setText(currentData.colors);
rarity.setText(currentData.rarity);
subTypes.setText(currentData.subTypes);
cardTypes.setText(currentData.cardTypes);
superTypes.setText(currentData.superTypes);
manaCosts.setText(currentData.manaCosts);
keyWords.setText(currentData.keyWords);
colorType.setSelectedItem(currentData.colorType);
cardText.setText(currentData.cardText);
updating=false;
}
}

View File

@@ -0,0 +1,135 @@
package forge.adventure.editor;
import forge.adventure.data.RewardData;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionListener;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class RewardsEditor extends JComponent{
DefaultListModel<RewardData> model = new DefaultListModel<>();
JList<RewardData> list = new JList<>(model);
JToolBar toolBar = new JToolBar("toolbar");
RewardEdit edit=new RewardEdit();
public class RewardDataRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if(!(value instanceof RewardData))
return label;
RewardData reward=(RewardData) value;
StringBuilder builder=new StringBuilder();
if(reward.type==null||reward.type.isEmpty())
builder.append("Reward");
else
builder.append(reward.type);
builder.append(" ");
builder.append(reward.count);
if(reward.addMaxCount>0)
{
builder.append("-");
builder.append(reward.count+reward.addMaxCount);
}
label.setText(builder.toString());
return label;
}
}
public void addButton(String name, ActionListener action)
{
JButton newButton=new JButton(name);
newButton.addActionListener(action);
toolBar.add(newButton);
}
public RewardsEditor()
{
list.setCellRenderer(new RewardsEditor.RewardDataRenderer());
list.addListSelectionListener(e -> updateEdit());
addButton("add",e->addReward());
addButton("remove",e->remove());
addButton("copy",e->copy());
BorderLayout layout=new BorderLayout();
setLayout(layout);
add(list, BorderLayout.LINE_START);
add(toolBar, BorderLayout.PAGE_START);
add(edit,BorderLayout.CENTER);
edit.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
emitChanged();
}
});
}
protected void emitChanged() {
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
if (listeners != null && listeners.length > 0) {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
}
private void copy() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
RewardData data=new RewardData(model.get(selected));
model.add(model.size(),data);
}
private void updateEdit() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
edit.setCurrentReward(model.get(selected));
}
void addReward()
{
RewardData data=new RewardData();
model.add(model.size(),data);
}
void remove()
{
int selected=list.getSelectedIndex();
if(selected<0)
return;
model.remove(selected);
}
public void setRewards(RewardData[] rewards) {
model.clear();
for (int i=0;i<rewards.length;i++) {
model.add(i,rewards[i]);
}
}
public RewardData[] getRewards() {
RewardData[] rewards= new RewardData[model.getSize()];
for(int i=0;i<model.getSize();i++)
{
rewards[i]=model.get(i);
}
return rewards;
}
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
}

View File

@@ -0,0 +1,69 @@
package forge.adventure.editor;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.Array;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import static java.awt.Image.SCALE_FAST;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class SwingAtlas {
HashMap<String, ArrayList<ImageIcon>> images=new HashMap<>();
public HashMap<String, ArrayList<ImageIcon>> getImages()
{
return images;
}
public SwingAtlas(FileHandle path)
{
if(!path.exists())
return;
TextureAtlas.TextureAtlasData data=new TextureAtlas.TextureAtlasData(path,path.parent(),false);
for(TextureAtlas.TextureAtlasData.Region region: new Array.ArrayIterator<>(data.getRegions()))
{
String name=region.name;
if(!images.containsKey(name))
{
images.put(name,new ArrayList<>());
}
ArrayList<ImageIcon> imageList=images.get(name);
try {
imageList.add(spriteToImage(region));
} catch (IOException e) {
e.printStackTrace();
}
}
}
private ImageIcon spriteToImage(TextureAtlas.TextureAtlasData.Region sprite) throws IOException {
BufferedImage img = ImageIO.read(sprite.page.textureFile.file());
return new ImageIcon(img.getSubimage(sprite.left,sprite.top, sprite.width, sprite.height).getScaledInstance(32,32,SCALE_FAST));
}
public ImageIcon get(String name) {
return images.get(name).get(0);
}
public boolean has(String name) {
return images.containsKey(name);
}
public ImageIcon getAny() {
if(images.isEmpty())
return null;
ArrayList<ImageIcon> imageList= images.get(images.keySet().iterator().next());
if(imageList.isEmpty())
return null;
return imageList.get(0);
}
}

View File

@@ -0,0 +1,52 @@
package forge.adventure.editor;
import forge.adventure.util.Config;
import org.apache.commons.lang3.tuple.Pair;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class SwingAtlasPreview extends Box {
private String sprite="";
Timer timer;
public SwingAtlasPreview() {
super(BoxLayout.Y_AXIS);
timer = new Timer(200, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
counter++;
for (Pair<JLabel, ArrayList<ImageIcon>> element : labels) {
element.getKey().setIcon(element.getValue().get(counter % element.getValue().size()));
}
}
});
}
int counter=0;
List<Pair<JLabel,ArrayList<ImageIcon>>> labels=new ArrayList<>();
public void setSpritePath(String sprite) {
removeAll();
counter=0;
labels.clear();
if(this.sprite.equals(sprite))
return;
this.sprite=sprite;
SwingAtlas atlas=new SwingAtlas(Config.instance().getFile(sprite));
for(Map.Entry<String, ArrayList<ImageIcon>> element:atlas.getImages().entrySet())
{
JLabel image=new JLabel(element.getValue().get(0));
add(new JLabel(element.getKey()));
add(image);
labels.add(Pair.of(image, element.getValue()));
}
timer.restart();
repaint();
}
}

View File

@@ -0,0 +1,101 @@
package forge.adventure.editor;
import forge.adventure.util.Config;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class TextListEdit extends Box {
JTextField edit=new JTextField();
JButton findButton=new JButton(UIManager.getIcon("add"));
JComboBox elements;
public TextListEdit(String[] possibleElements) {
super(BoxLayout.X_AXIS);
findButton.addActionListener(e->find());
add(edit);
//add(findButton);
elements= new JComboBox(possibleElements);
add(elements);
}
public TextListEdit()
{
this(new String[0]);
}
JTextField getEdit()
{
return edit;
}
private void find() {
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File(Config.instance().getFilePath("")));
fc.setMultiSelectionEnabled(false);
if (fc.showOpenDialog(this) ==
JFileChooser.APPROVE_OPTION) {
File selected = fc.getSelectedFile();
try {
if (selected != null&&selected.getCanonicalPath().startsWith(new File(Config.instance().getFilePath("")).getCanonicalPath())) {
edit.setText(selected.getCanonicalPath().substring(new File(Config.instance().getFilePath("")).getCanonicalPath().length()+1));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void setText(String[] itemName) {
if(itemName==null)
edit.setText("");
else
edit.setText(String.join(";",itemName));
}
public void setText(int[] intValues) {
if(intValues==null)
{
edit.setText("");
return;
}
StringBuilder values= new StringBuilder();
for(int i=0;i<intValues.length;i++)
{
values.append(intValues[i]);
if(intValues.length>i+2)
values.append(";");
}
edit.setText(values.toString());
}
public String[] getList() {
return edit.getText().isEmpty()?null:edit.getText().split(";");
}
public int[] getListAsInt() {
if(edit.getText().isEmpty())
return null;
String[] stringList=getList();
int[] retList=new int[stringList.length];
for(int i=0;i<retList.length;i++)
{
String intName=stringList[i];
try
{
retList[i] = Integer.valueOf(intName);
}
catch (NumberFormatException e)
{
retList[i] =0;
}
}
return retList;
}
}

View File

@@ -0,0 +1,118 @@
package forge.adventure.scene;
import com.badlogic.gdx.scenes.scene2d.Stage;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.world.AdventurePlayer;
import forge.deck.Deck;
import forge.deck.FDeckEditor;
import forge.gamemodes.quest.QuestMode;
import forge.gamemodes.quest.QuestSpellShop;
import forge.gamemodes.quest.data.DeckConstructionRules;
import forge.gamemodes.quest.data.QuestData;
import forge.item.PaperCard;
import forge.itemmanager.ColumnDef;
import forge.itemmanager.ItemColumn;
import forge.itemmanager.ItemManagerConfig;
import forge.model.FModel;
import forge.screens.FScreen;
import forge.toolbox.FEvent;
import java.util.HashMap;
import java.util.Map;
/**
* DeckEditScene
* scene class that contains the Deck editor
*/
public class DeckEditScene extends ForgeScene {
public class AdventureDeckEditor extends FDeckEditor {
public AdventureDeckEditor(boolean commander) {
super(commander ? EditorType.QuestCommander : EditorType.Quest, "", false, new FEvent.FEventHandler() {
@Override
public void handleEvent(FEvent e) {
AdventureApplicationAdapter.instance.switchToLast();
}
});
}
@Override
public void onActivate() {
super.onActivate();
QuestSpellShop.updateDecksForEachCard();
}
@Override
protected Map<ColumnDef, ItemColumn> getColOverrides(ItemManagerConfig config) {
Map<ColumnDef, ItemColumn> colOverrides = new HashMap<>();
switch (config) {
case QUEST_EDITOR_POOL:
ItemColumn.addColOverride(config, colOverrides, ColumnDef.NEW, FModel.getQuest().getCards().getFnNewCompare(), FModel.getQuest().getCards().getFnNewGet());
break;
case QUEST_DECK_EDITOR:
ItemColumn.addColOverride(config, colOverrides, ColumnDef.NEW, FModel.getQuest().getCards().getFnNewCompare(), FModel.getQuest().getCards().getFnNewGet());
ItemColumn.addColOverride(config, colOverrides, ColumnDef.DECKS, QuestSpellShop.fnDeckCompare, QuestSpellShop.fnDeckGet);
break;
default:
colOverrides = null; //shouldn't happen
break;
}
return colOverrides;
}
public void refresh() {
for(TabPage page:tabPages)
{
if(page instanceof CardManagerPage)
((CardManagerPage)page).refresh();
}
}
}
AdventureDeckEditor screen;
Stage stage;
public DeckEditScene() {
}
@Override
public void dispose() {
if (stage != null)
stage.dispose();
}
@Override
public void enter() {
QuestData data = new QuestData("", 0, QuestMode.Classic, null, false, "", DeckConstructionRules.Commander);
FModel.getQuest().load(data);
FModel.getQuest().getCards().getCardpool().clear();
for (PaperCard card : AdventurePlayer.current().getCards())
FModel.getQuest().getCards().addSingleCard(card, 1);
Deck deck = AdventurePlayer.current().getDeck();
getScreen();
screen.getEditorType().getController().setDeck(deck);
screen.refresh();
super.enter();
}
@Override
public FScreen getScreen() {
return screen==null?screen = new AdventureDeckEditor(false):screen;
}
}

View File

@@ -0,0 +1,130 @@
package forge.adventure.scene;
import forge.LobbyPlayer;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.character.EnemySprite;
import forge.adventure.character.PlayerSprite;
import forge.assets.FSkin;
import forge.screens.FScreen;
import forge.screens.match.MatchController;
import forge.adventure.util.Current;
import forge.adventure.util.Config;
import forge.adventure.world.AdventurePlayer;
import forge.deck.Deck;
import forge.game.GameRules;
import forge.game.GameType;
import forge.game.player.Player;
import forge.game.player.RegisteredPlayer;
import forge.gamemodes.match.HostedMatch;
import forge.gui.interfaces.IGuiGame;
import forge.player.GamePlayerUtil;
import forge.player.PlayerControllerHuman;
import forge.trackable.TrackableCollection;
import java.util.*;
/**
* DuelScene
* Forge screen scene that contains the duel screen
*/
public class DuelScene extends ForgeScene {
//GameLobby lobby;
HostedMatch hostedMatch;
EnemySprite enemy;
PlayerSprite player;
RegisteredPlayer humanPlayer;
public DuelScene() {
}
@Override
public void dispose() {
}
public void GameEnd() {
Scene last= AdventureApplicationAdapter.instance.switchToLast();
if(last instanceof HudScene)
{
((HudScene)last).stage.setWinner(humanPlayer == hostedMatch.getGame().getMatch().getWinner());
}
}
@Override
public void enter() {
Set<GameType> appliedVariants = new HashSet<>();
appliedVariants.add(GameType.Constructed);
List<RegisteredPlayer> players = new ArrayList<>();
Deck playerDeck=(Deck)AdventurePlayer.current().getDeck().copyTo("PlayerDeckCopy");
int missingCards= Config.instance().getConfigData().minDeckSize-playerDeck.getMain().countAll();
if(missingCards>0)
playerDeck.getMain().add("Wastes",missingCards);
humanPlayer = RegisteredPlayer.forVariants(2, appliedVariants,playerDeck, null, false, null, null);
LobbyPlayer playerObject = GamePlayerUtil.getGuiPlayer();
FSkin.getAvatars().put(90001, Current.player().avatar());
playerObject.setAvatarIndex(90001);
humanPlayer.setPlayer(playerObject);
humanPlayer.setStartingLife(Current.player().getLife());
Current.setLatestDeck(enemy.getData().generateDeck());
RegisteredPlayer aiPlayer = RegisteredPlayer.forVariants(2, appliedVariants, Current.latestDeck(), null, false, null, null);
LobbyPlayer enemyPlayer = GamePlayerUtil.createAiPlayer();
FSkin.getAvatars().put(90000, this.enemy.getAvatar());
enemyPlayer.setAvatarIndex(90000);
enemyPlayer.setName(this.enemy.getData().name);
aiPlayer.setPlayer(enemyPlayer);
aiPlayer.setStartingLife(Math.round((float)enemy.getData().life*Current.player().getDifficulty().enemyLifeFactor));
players.add(humanPlayer);
players.add(aiPlayer);
final Map<RegisteredPlayer, IGuiGame> guiMap = new HashMap<>();
guiMap.put(humanPlayer, MatchController.instance);
hostedMatch = MatchController.hostMatch();
GameRules rules = new GameRules(GameType.Constructed);
rules.setPlayForAnte(false);
rules.setMatchAnteRarity(true);
rules.setGamesPerMatch(1);
rules.setManaBurn(false);
hostedMatch.setEndGameHook(() -> GameEnd());
hostedMatch.startMatch(rules, appliedVariants, players, guiMap);
MatchController.instance.setGameView(hostedMatch.getGameView());
for (final Player p : hostedMatch.getGame().getPlayers()) {
if (p.getController() instanceof PlayerControllerHuman) {
final PlayerControllerHuman humanController = (PlayerControllerHuman) p.getController();
humanController.setGui(MatchController.instance);
MatchController.instance.setOriginalGameController(p.getView(), humanController);
MatchController.instance.openView(new TrackableCollection<>(p.getView()));
}
}
super.enter();
}
@Override
public FScreen getScreen() {
return MatchController.getView();
}
public void setEnemy(EnemySprite data) {
this.enemy = data;
}
public void setPlayer(PlayerSprite sprite) {
this.player = sprite;
}
}

View File

@@ -0,0 +1,306 @@
package forge.adventure.scene;
import com.badlogic.gdx.Input;
import forge.Forge;
import forge.screens.match.MatchController;
import forge.toolbox.FContainer;
import forge.toolbox.FDisplayObject;
import forge.toolbox.FGestureAdapter;
import forge.toolbox.FOverlay;
import forge.util.Utils;
import forge.gui.error.BugReporter;
import java.util.ArrayList;
import java.util.List;
/**
* ForgeInput
* Handles input for forge screens
*/
public class ForgeInput extends FGestureAdapter {
private static final List<FDisplayObject> potentialListeners = new ArrayList<>();
private static char lastKeyTyped;
private static boolean keyTyped, shiftKeyDown;
private final ForgeScene forgeScene;
private final Forge.KeyInputAdapter keyInputAdapter = null;
//mouseMoved and scrolled events for desktop version
private int mouseMovedX, mouseMovedY;
public ForgeInput(ForgeScene forgeScene) {
this.forgeScene=forgeScene;
}
@Override
public boolean keyDown(int keyCode) {
if (keyCode == Input.Keys.MENU) {
//showMenu();
return true;
}
if (keyCode == Input.Keys.SHIFT_LEFT || keyCode == Input.Keys.SHIFT_RIGHT) {
shiftKeyDown = true;
}
// Cursor keys emulate swipe gestures
// First we touch the screen and later swipe (fling) in the direction of the key pressed
if (keyCode == Input.Keys.LEFT) {
touchDown(0, 0, 0, 0);
return fling(1000, 0);
}
if (keyCode == Input.Keys.RIGHT) {
touchDown(0, 0, 0, 0);
return fling(-1000, 0);
}
if (keyCode == Input.Keys.UP) {
touchDown(0, 0, 0, 0);
return fling(0, -1000);
}
if (keyCode == Input.Keys.DOWN) {
touchDown(0, 0, 0, 0);
return fling(0, 1000);
}
/*
if(keyCode == Input.Keys.BACK){
if (destroyThis)
deviceAdapter.exit();
else if(onHomeScreen() && isLandscapeMode())
back();
}
*/
if (keyInputAdapter == null) {
if (Forge.KeyInputAdapter.isModifierKey(keyCode)) {
return false; //don't process modifiers keys for unknown adapter
}
//if no active key input adapter, give current screen or overlay a chance to handle key
FContainer container = FOverlay.getTopOverlay();
if (container == null) {
container = MatchController.getView();
if (container == null) {
return false;
}
}
return container.keyDown(keyCode);
}
return keyInputAdapter.keyDown(keyCode);
}
@Override
public boolean keyUp(int keyCode) {
keyTyped = false; //reset on keyUp
if (keyCode == Input.Keys.SHIFT_LEFT || keyCode == Input.Keys.SHIFT_RIGHT) {
shiftKeyDown = false;
}
if (keyInputAdapter != null) {
return keyInputAdapter.keyUp(keyCode);
}
return false;
}
@Override
public boolean keyTyped(char ch) {
if (keyInputAdapter != null) {
if (ch >= ' ' && ch <= '~') { //only process this event if character is printable
//prevent firing this event more than once for the same character on the same key down, otherwise it fires too often
if (lastKeyTyped != ch || !keyTyped) {
keyTyped = true;
lastKeyTyped = ch;
return keyInputAdapter.keyTyped(ch);
}
}
}
return false;
}
private void updatePotentialListeners(int x, int y) {
potentialListeners.clear();
//base potential listeners on object containing touch down point
for (FOverlay overlay : FOverlay.getOverlaysTopDown()) {
if (overlay.isVisibleOnScreen(forgeScene.getScreen())) {
overlay.buildTouchListeners(x, y, potentialListeners);
if (overlay.preventInputBehindOverlay()) {
return;
}
}
}
forgeScene.buildTouchListeners(x, y, potentialListeners);
}
@Override
public boolean touchDown(int x, int y, int pointer, int button) {
if (pointer == 0) { //don't change listeners when second finger goes down for zoom
updatePotentialListeners(x, y);
if (keyInputAdapter != null) {
if (!keyInputAdapter.allowTouchInput() || !potentialListeners.contains(keyInputAdapter.getOwner())) {
//endKeyInput(); //end key input if needed
}
}
}
return super.touchDown(x, y, pointer, button);
}
@Override
public boolean press(float x, float y) {
try {
for (FDisplayObject listener : potentialListeners) {
if (listener.press(listener.screenToLocalX(x), listener.screenToLocalY(y))) {
return true;
}
}
return false;
} catch (Exception ex) {
BugReporter.reportException(ex);
return true;
}
}
@Override
public boolean release(float x, float y) {
try {
for (FDisplayObject listener : potentialListeners) {
if (listener.release(listener.screenToLocalX(x), listener.screenToLocalY(y))) {
return true;
}
}
return false;
} catch (Exception ex) {
BugReporter.reportException(ex);
return true;
}
}
@Override
public boolean longPress(float x, float y) {
try {
for (FDisplayObject listener : potentialListeners) {
if (listener.longPress(listener.screenToLocalX(x), listener.screenToLocalY(y))) {
return true;
}
}
return false;
} catch (Exception ex) {
BugReporter.reportException(ex);
return true;
}
}
@Override
public boolean tap(float x, float y, int count) {
if (shiftKeyDown && flick(x, y)) {
return true; //give flick logic a chance to handle Shift+click
}
try {
for (FDisplayObject listener : potentialListeners) {
if (listener.tap(listener.screenToLocalX(x), listener.screenToLocalY(y), count)) {
return true;
}
}
return false;
} catch (Exception ex) {
BugReporter.reportException(ex);
return true;
}
}
@Override
public boolean flick(float x, float y) {
try {
for (FDisplayObject listener : potentialListeners) {
if (listener.flick(listener.screenToLocalX(x), listener.screenToLocalY(y))) {
return true;
}
}
return false;
} catch (Exception ex) {
BugReporter.reportException(ex);
return true;
}
}
@Override
public boolean fling(float velocityX, float velocityY) {
try {
for (FDisplayObject listener : potentialListeners) {
if (listener.fling(velocityX, velocityY)) {
return true;
}
}
return false;
} catch (Exception ex) {
BugReporter.reportException(ex);
return true;
}
}
@Override
public boolean pan(float x, float y, float deltaX, float deltaY, boolean moreVertical) {
try {
for (FDisplayObject listener : potentialListeners) {
if (listener.pan(listener.screenToLocalX(x), listener.screenToLocalY(y), deltaX, deltaY, moreVertical)) {
return true;
}
}
return false;
} catch (Exception ex) {
BugReporter.reportException(ex);
return true;
}
}
@Override
public boolean panStop(float x, float y) {
try {
for (FDisplayObject listener : potentialListeners) {
if (listener.panStop(listener.screenToLocalX(x), listener.screenToLocalY(y))) {
return true;
}
}
return false;
} catch (Exception ex) {
BugReporter.reportException(ex);
return true;
}
}
@Override
public boolean zoom(float x, float y, float amount) {
try {
for (FDisplayObject listener : potentialListeners) {
if (listener.zoom(listener.screenToLocalX(x), listener.screenToLocalY(y), amount)) {
return true;
}
}
return false;
} catch (Exception ex) {
BugReporter.reportException(ex);
return true;
}
}
@Override
public boolean mouseMoved(int x, int y) {
mouseMovedX = x;
mouseMovedY = y;
return true;
}
@Override
public boolean scrolled(float amountX, float amountY) {
updatePotentialListeners(mouseMovedX, mouseMovedY);
if (Forge.KeyInputAdapter.isCtrlKeyDown()) { //zoom in or out based on amount
return zoom(mouseMovedX, mouseMovedY, -Utils.AVG_FINGER_WIDTH * amountY);
}
boolean handled;
if (Forge.KeyInputAdapter.isShiftKeyDown()) {
handled = pan(mouseMovedX, mouseMovedY, -Utils.AVG_FINGER_WIDTH * amountX, 0, false);
} else {
handled = pan(mouseMovedX, mouseMovedY, 0, -Utils.AVG_FINGER_HEIGHT * amountY, true);
}
if (panStop(mouseMovedX, mouseMovedY)) {
handled = true;
}
return handled;
}
}

View File

@@ -0,0 +1,105 @@
package forge.adventure.scene;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import forge.adventure.AdventureApplicationAdapter;
import forge.Forge;
import forge.Graphics;
import forge.animation.ForgeAnimation;
import forge.assets.ImageCache;
import forge.screens.FScreen;
import forge.toolbox.FDisplayObject;
import forge.toolbox.FOverlay;
import forge.gamemodes.match.LobbySlotType;
import forge.interfaces.IUpdateable;
import java.util.List;
/**
* base class to render base forge screens like the deck editor and matches
*/
public abstract class ForgeScene extends Scene implements IUpdateable {
//GameLobby lobby;
Graphics localGraphics;
ForgeInput input=new ForgeInput(this);
@Override
public void dispose() {
}
@Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear the screen.
if (getScreen() == null) {
return;
}
localGraphics.begin(AdventureApplicationAdapter.instance.getCurrentWidth(), AdventureApplicationAdapter.instance.getCurrentHeight());
getScreen().screenPos.setSize(AdventureApplicationAdapter.instance.getCurrentWidth(), AdventureApplicationAdapter.instance.getCurrentHeight());
if (getScreen().getRotate180()) {
localGraphics.startRotateTransform(AdventureApplicationAdapter.instance.getCurrentWidth() / 2f, AdventureApplicationAdapter.instance.getCurrentHeight() / 2f, 180);
}
getScreen().draw(localGraphics);
if (getScreen().getRotate180()) {
localGraphics.endTransform();
}
for (FOverlay overlay : FOverlay.getOverlays()) {
if (overlay.isVisibleOnScreen(getScreen())) {
overlay.screenPos.setSize(AdventureApplicationAdapter.instance.getCurrentWidth(), AdventureApplicationAdapter.instance.getCurrentHeight());
overlay.setSize(AdventureApplicationAdapter.instance.getCurrentWidth(), AdventureApplicationAdapter.instance.getCurrentHeight()); //update overlay sizes as they're rendered
if (overlay.getRotate180()) {
localGraphics.startRotateTransform(AdventureApplicationAdapter.instance.getCurrentHeight() / 2f, AdventureApplicationAdapter.instance.getCurrentHeight() / 2f, 180);
}
overlay.draw(localGraphics);
if (overlay.getRotate180()) {
localGraphics.endTransform();
}
}
}
localGraphics.end();
//Batch.end();
}
@Override
public void act(float delta) {
ImageCache.allowSingleLoad();
ForgeAnimation.advanceAll();
}
@Override
public void enter() {
if(getScreen()!=null)
getScreen().setSize(AdventureApplicationAdapter.instance.getCurrentWidth(), AdventureApplicationAdapter.instance.getCurrentHeight());
Forge.openScreen(getScreen());
Gdx.input.setInputProcessor(input);
}
public abstract FScreen getScreen();
public void buildTouchListeners(int x, int y, List<FDisplayObject> potentialListeners) {
if(getScreen()!=null)
getScreen().buildTouchListeners(x, y, potentialListeners);
}
@Override
public void resLoaded() {
localGraphics = AdventureApplicationAdapter.instance.getGraphics();
}
@Override
public void update(boolean fullUpdate) {
}
@Override
public void update(int slot, LobbySlotType type) {
}
}

View File

@@ -0,0 +1,46 @@
package forge.adventure.scene;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import forge.adventure.stage.WorldStage;
/**
* Game scene main over world scene
* does render the WorldStage and HUD
*/
public class GameScene extends HudScene {
public GameScene() {
super(WorldStage.getInstance());
}
@Override
public void dispose() {
stage.dispose();
}
@Override
public void act(float delta) {
stage.act(delta);
}
@Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.draw();
hud.draw();
}
@Override
public void resLoaded() {
}
}

View File

@@ -0,0 +1,119 @@
package forge.adventure.scene;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL20;
import forge.adventure.stage.GameHUD;
import forge.adventure.stage.GameStage;
/**
* Hud base scene
*/
public class HudScene extends Scene implements InputProcessor {
GameHUD hud;
GameStage stage;
protected HudScene(GameStage s) {
stage = s;
hud = GameHUD.getInstance();
}
@Override
public boolean leave() {
stage.leave();
return true;
}
@Override
public void enter() {
Gdx.input.setInputProcessor(this);
stage.enter();
hud.enter();
}
@Override
public void dispose() {
stage.dispose();
}
@Override
public void act(float delta)
{
stage.act(delta);
hud.act(delta);
}
@Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.draw();
hud.draw();
}
@Override
public void resLoaded() {
}
@Override
public boolean keyDown(int keycode) {
if (hud.keyDown(keycode))
return true;
return stage.keyDown(keycode);
}
@Override
public boolean keyUp(int keycode) {
if (hud.keyUp(keycode))
return true;
return stage.keyUp(keycode);
}
@Override
public boolean keyTyped(char character) {
if (hud.keyTyped(character))
return true;
return stage.keyTyped(character);
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
if (hud.touchDown(screenX, screenY, pointer, button))
return true;
return stage.touchDown(screenX, screenY, pointer, button);
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
if (hud.touchUp(screenX, screenY, pointer, button))
return true;
return stage.touchUp(screenX, screenY, pointer, button);
}
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
if (hud.touchDragged(screenX, screenY, pointer))
return true;
return stage.touchDragged(screenX, screenY, pointer);
}
@Override
public boolean mouseMoved(int screenX, int screenY) {
if (hud.mouseMoved(screenX, screenY))
return true;
return stage.mouseMoved(screenX, screenY);
}
@Override
public boolean scrolled(float amountX, float amountY) {
if (hud.scrolled(amountX, amountY))
return true;
return stage.scrolled(amountX, amountY);
}
}

View File

@@ -0,0 +1,41 @@
package forge.adventure.scene;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.util.Current;
/**
* Scene for the Inn in towns
*
*/
public class InnScene extends UIScene {
public InnScene()
{
super("ui/inn.json");
}
public void done()
{
AdventureApplicationAdapter.instance.switchToLast();
}
public void heal()
{
Current.player().heal();
}
@Override
public void act(float delta) {
stage.act(delta);
}
@Override
public void resLoaded() {
super.resLoaded();
ui.onButtonPress("done",()->done());
ui.onButtonPress("heal",()->heal());
TextButton doneButton = ui.findActor("done");
}
}

View File

@@ -0,0 +1,136 @@
package forge.adventure.scene;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Array;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.data.DifficultyData;
import forge.adventure.data.HeroListData;
import forge.adventure.util.Config;
import forge.adventure.util.Selector;
import forge.adventure.world.WorldSave;
import forge.deck.Deck;
import forge.localinstance.properties.ForgePreferences;
import forge.model.FModel;
import forge.player.GamePlayerUtil;
import forge.util.NameGenerator;
import java.util.Random;
/**
* NewGame scene that contains the character creation
*/
public class NewGameScene extends UIScene {
TextField selectedName;
Deck[] starterDeck;
private Image avatarImage;
private int avatarIndex = 0;
private Selector race;
private Selector deck;
private Selector gender;
private Selector difficulty;
public NewGameScene() {
super("ui/new_game.json");
}
public boolean start() {
FModel.getPreferences().setPref(ForgePreferences.FPref.UI_ENABLE_MUSIC, false);
WorldSave.generateNewWorld(selectedName.getText(),
gender.getCurrentIndex() == 0,
race.getCurrentIndex(),
avatarIndex,
deck.getCurrentIndex(),
Config.instance().getConfigData().difficulties[difficulty.getCurrentIndex()],0);
GamePlayerUtil.getGuiPlayer().setName(selectedName.getText());
//image = new Texture(img);
AdventureApplicationAdapter.instance.switchScene(SceneType.GameScene.instance);
return true;
}
public boolean back() {
AdventureApplicationAdapter.instance.switchScene(SceneType.StartScene.instance);
return true;
}
@Override
public void resLoaded() {
super.resLoaded();
selectedName = ui.findActor("nameField");
selectedName.setText(NameGenerator.getRandomName("Any", "Any", ""));
avatarImage = ui.findActor("avatarPreview");
gender = ui.findActor("gender");
gender.setTextList(new String[]{"Male", "Female"});
gender.addListener(event -> updateAvatar());
Random rand=new Random();
deck = ui.findActor("deck");
starterDeck = Config.instance().starterDecks();
Array<String> stringList = new Array<>(starterDeck.length);
for (Deck deck : starterDeck)
stringList.add(deck.getName());
deck.setTextList(stringList);
race = ui.findActor("race");
race.addListener(event -> updateAvatar());
race.setTextList(HeroListData.getRaces());
difficulty = ui.findActor("difficulty");
Array<String> diffList = new Array<>(starterDeck.length);
int i=0;
int startingDifficulty=0;
for (DifficultyData diff : Config.instance().getConfigData().difficulties)
{
if(diff.startingDifficulty)
startingDifficulty=i;
diffList.add(diff.name);
i++;
}
difficulty.setTextList(diffList);
difficulty.setCurrentIndex(startingDifficulty);
avatarIndex=rand.nextInt();
gender.setCurrentIndex(rand.nextInt());
deck.setCurrentIndex(rand.nextInt());
race.setCurrentIndex(rand.nextInt());
ui.onButtonPress("back", this::back);
ui.onButtonPress("start", this::start);
ui.onButtonPress("leftAvatar", this::leftAvatar);
ui.onButtonPress("rightAvatar", this::rightAvatar);
updateAvatar();
}
private void rightAvatar() {
avatarIndex++;
updateAvatar();
}
private void leftAvatar() {
avatarIndex--;
updateAvatar();
}
private boolean updateAvatar() {
avatarImage.setDrawable(new TextureRegionDrawable(HeroListData.getAvatar(race.getCurrentIndex(), gender.getCurrentIndex() != 0, avatarIndex)));
return false;
}
@Override
public void create() {
}
@Override
public void enter() {
Gdx.input.setInputProcessor(stage); //Start taking input from the ui
}
}

View File

@@ -0,0 +1,280 @@
package forge.adventure.scene;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Array;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.character.ShopActor;
import forge.assets.ImageCache;
import forge.adventure.util.CardUtil;
import forge.adventure.util.Current;
import forge.adventure.util.Reward;
import forge.adventure.util.RewardActor;
import forge.adventure.world.AdventurePlayer;
import forge.adventure.world.PointOfInterestChanges;
import forge.adventure.world.WorldSave;
/**
* Displays the rewards of a fight or a treasure
*/
public class RewardScene extends UIScene {
private TextButton doneButton;
public enum Type
{
Shop,
Loot
}
Type type;
Array<Actor> generated =new Array<>();
static public final float CARD_WIDTH =550f;
static public final float CARD_HEIGHT =400f;
static public final float CARD_WIDTH_TO_HEIGHT =CARD_WIDTH/CARD_HEIGHT;
public RewardScene()
{
super("ui/items.json");
}
boolean doneClicked=false;
float flipCountDown=1.0f;
public boolean done()
{
if(doneClicked)
return true;
if(type==Type.Loot)
{
boolean wait=false;
for(Actor actor: new Array.ArrayIterator<>(generated))
{
if(!(actor instanceof RewardActor))
{
continue;
}
RewardActor reward=(RewardActor) actor;
AdventurePlayer.current().addReward(reward.getReward());
if(!reward.isFlipped())
{
wait = true;
reward.flip();
}
}
if(wait)
{
flipCountDown=3.0f;
doneClicked=true;
}
else
{
AdventureApplicationAdapter.instance.switchToLast();
}
}
else
{
AdventureApplicationAdapter.instance.switchToLast();
}
return true;
}
@Override
public void act(float delta) {
stage.act(delta);
ImageCache.allowSingleLoad();
if(doneClicked)
{
if(type==Type.Loot)
flipCountDown-=Gdx.graphics.getDeltaTime();
if(flipCountDown<=0)
{
AdventureApplicationAdapter.instance.switchToLast();
}
}
}
@Override
public void resLoaded() {
super.resLoaded();
ui.onButtonPress("done",()->done());
doneButton=ui.findActor("done");
}
public void loadRewards(Array<Reward> newRewards, Type type, ShopActor shopActor)
{
this.type=type;
doneClicked=false;
for(Actor actor: new Array.ArrayIterator<>(generated))
{
actor.remove();
if(actor instanceof RewardActor)
{
((RewardActor)actor).dispose();
}
}
generated.clear();
Actor card=ui.findActor("cards");
// card.setDrawable(new TextureRegionDrawable(new Texture(Res.CurrentRes.GetFile("ui/transition.png"))));
float targetWidth = card.getWidth();
float targetHeight = card.getHeight();
float xOff = card.getX();
float yOff = card.getY();
int numberOfRows=0;
float cardWidth=0;
float cardHeight=0;
float bestCardHeight=0;
int numberOfColumns=0;
float targetArea=targetHeight*targetWidth;
float oldCardArea=0;
float newArea=0;
switch (type) {
case Shop:
doneButton.setText("Return");
break;
case Loot:
doneButton.setText("Take all");
break;
}
for(int h=1;h<targetHeight;h++)
{
cardHeight=h;
if(type==Type.Shop)
{
cardHeight+=doneButton.getHeight();
}
//cardHeight=targetHeight/i;
cardWidth=h/ CARD_WIDTH_TO_HEIGHT;
newArea=newRewards.size*cardWidth*cardHeight;
int rows=(int) (targetHeight/cardHeight);
int cols =(int)Math.ceil(newRewards.size/(double)rows);
if(newArea>oldCardArea&&newArea<=targetArea&&rows*cardHeight<targetHeight&&cols*cardWidth<targetWidth)
{
oldCardArea=newArea;
numberOfRows= rows;
numberOfColumns =cols;
bestCardHeight=h;
}
}
cardHeight=bestCardHeight;
cardWidth=bestCardHeight/ CARD_WIDTH_TO_HEIGHT;
yOff+=(targetHeight-(cardHeight*numberOfRows))/2f;
xOff+=(targetWidth-(cardWidth*numberOfColumns))/2f;
float spacing=2;
int i=0;
for(Reward reward:new Array.ArrayIterator<>(newRewards))
{
boolean skipCard=false;
if(type==Type.Shop)
{
if(shopActor.getMapStage().getChanges().wasCardBought(shopActor.getObjectID(),i))
{
skipCard=true;
}
}
int currentRow=(i/numberOfColumns);
float lastRowXAdjust=0;
if(currentRow==numberOfRows-1)
{
int lastRowCount=newRewards.size%numberOfColumns;
if(lastRowCount!=0)
lastRowXAdjust=((numberOfColumns*cardWidth)-(lastRowCount*cardWidth))/2;
}
RewardActor actor=new RewardActor(reward,type==Type.Loot);
actor.setBounds(lastRowXAdjust+xOff+cardWidth*(i%numberOfColumns)+spacing,yOff+cardHeight*currentRow+spacing,cardWidth-spacing*2,cardHeight-spacing*2);
if(type==Type.Shop)
{
if(currentRow!=((i+1)/numberOfColumns))
yOff+=doneButton.getHeight();
TextButton buyCardButton=new BuyButton(shopActor.getObjectID(),i,shopActor.getMapStage().getChanges(),actor,doneButton);
generated.add(buyCardButton);
if(!skipCard)
{
stage.addActor(buyCardButton);
}
}
generated.add(actor);
if(!skipCard)
{
stage.addActor(actor);
}
i++;
}
updateBuyButtons();
}
private void updateBuyButtons() {
for(Actor actor: new Array.ArrayIterator<>(generated))
{
if(actor instanceof BuyButton)
{
((BuyButton)actor).update();
}
}
}
private class BuyButton extends TextButton {
private final int objectID;
private final int index;
private final PointOfInterestChanges changes;
RewardActor reward;
int price;
void update(){
setDisabled(WorldSave.getCurrentSave().getPlayer().getGold()< price);
}
public BuyButton(int id, int i, PointOfInterestChanges ch, RewardActor actor, TextButton style) {
super("",style.getStyle());
this.objectID = id;
this.index = i;
this.changes = ch;
reward=actor;
setHeight(style.getHeight());
setWidth(actor.getWidth());
setX(actor.getX());
setY(actor.getY()-getHeight());
price= CardUtil.getCardPrice(actor.getReward().getCard());
setText("Buy for "+price);
addListener(new ClickListener(){
@Override
public void clicked (InputEvent event, float x, float y) {
if(Current.player().getGold()>= price)
{
changes.buyCard(objectID,index);
Current.player().takeGold(price);
Current.player().addReward(reward.getReward());
setDisabled(true);
reward.flip();
remove();
updateBuyButtons();
}
}
});
}
}
}

View File

@@ -0,0 +1,205 @@
package forge.adventure.scene;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.IntMap;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.util.Controls;
import forge.adventure.world.WorldSave;
import forge.adventure.world.WorldSaveHeader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.zip.InflaterInputStream;
/**
* Scene to load and save the game.
*
*/
public class SaveLoadScene extends UIScene {
private final IntMap<TextButton> buttons = new IntMap<>();
IntMap<WorldSaveHeader> previews = new IntMap<>();
Color defColor;
Table layout;
boolean save = true;
Dialog dialog;
TextField textInput;
Label header;
int currentSlot = -3;
Image previewImage;
TextButton saveLoadButton;
public SaveLoadScene() {
super("ui/save_load.json");
}
private void addSaveSlot(String name, int i) {
layout.add(Controls.newLabel(name));
TextButton button = Controls.newTextButton("...");
button.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
try {
select(i);
} catch (Exception e) {
e.printStackTrace();
}
}
});
layout.add(button).expandX();
buttons.put(i, button);
layout.row();
}
public void back() {
AdventureApplicationAdapter.instance.switchToLast();
}
public boolean select(int slot) {
currentSlot = slot;
if (previews.containsKey(slot)) {
WorldSaveHeader header = previews.get(slot);
if (header.preview != null) {
previewImage.setDrawable(new TextureRegionDrawable(new Texture(header.preview)));
previewImage.layout();
}
}
for (IntMap.Entry<TextButton> butt : new IntMap.Entries<TextButton> (buttons)) {
butt.value.setColor(defColor);
}
if (buttons.containsKey(slot)) {
TextButton button = buttons.get(slot);
button.setColor(Color.RED);
}
return true;
}
public void loadSave() {
if (save) {
textInput.setText("Save Game " + currentSlot);
dialog.show(stage);
stage.setKeyboardFocus(textInput);
} else {
if(WorldSave.load(currentSlot))
AdventureApplicationAdapter.instance.switchScene(SceneType.GameScene.instance);
}
}
public boolean saveAbort() {
dialog.hide();
return true;
}
public void save() {
dialog.hide();
if( WorldSave.getCurrentSave().save(textInput.getText(), currentSlot))
{
updateFiles();
AdventureApplicationAdapter.instance.switchScene(SceneType.GameScene.instance);
}
}
private void updateFiles() {
File f = new File(WorldSave.getSaveDir());
f.mkdirs();
File[] names = f.listFiles();
if(names==null)
throw new RuntimeException("Can not find save directory");
previews.clear();
for (File name : names) {
if (WorldSave.isSafeFile(name.getName())) {
try {
try (FileInputStream fos = new FileInputStream(name.getAbsolutePath());
InflaterInputStream inf = new InflaterInputStream(fos);
ObjectInputStream oos = new ObjectInputStream(inf)) {
int slot=WorldSave.filenameToSlot(name.getName());
WorldSaveHeader header = (WorldSaveHeader) oos.readObject();
buttons.get(slot).setText(header.name);
previews.put(slot, header);
}
} catch (ClassNotFoundException | IOException | GdxRuntimeException e) {
}
}
}
}
public void setSaveGame(boolean save) {
if (save) {
header.setText("Save game");
saveLoadButton.setText("Save");
} else {
header.setText("Load game");
saveLoadButton.setText("Load");
}
this.save = save;
}
@Override
public void enter() {
select(-3);
updateFiles();
super.enter();
}
@Override
public void resLoaded() {
super.resLoaded();
layout = new Table();
layout.setFillParent(true);
stage.addActor(layout);
dialog = Controls.newDialog("Save");
textInput = Controls.newTextField("");
dialog.getButtonTable().add(Controls.newLabel("Name your new save file.")).colspan(2);
dialog.getButtonTable().row();
dialog.getButtonTable().add(Controls.newLabel("Name:")).align(Align.left);
dialog.getButtonTable().add(textInput).fillX().expandX();
dialog.getButtonTable().row();
dialog.getButtonTable().add(Controls.newTextButton("Save", () -> save())).align(Align.left);
dialog.getButtonTable().add(Controls.newTextButton("Abort", () -> saveAbort())).align(Align.left);
previewImage = ui.findActor("preview");
header = Controls.newLabel("Save");
header.setHeight(header.getHeight() * 2);
layout.add(header).colspan(2).align(Align.center);
layout.row();
addSaveSlot("Auto save", -2);
addSaveSlot("Quick save", -1);
for (int i = 1; i < 11; i++)
addSaveSlot("Slot:" + i, i);
saveLoadButton = ui.findActor("save");
ui.onButtonPress("save",()-> loadSave());
ui.onButtonPress("return",()-> back());
defColor = saveLoadButton.getColor();
ScrollPane scrollPane = ui.findActor("saveSlots");
scrollPane.setActor(layout);
}
}

View File

@@ -0,0 +1,49 @@
package forge.adventure.scene;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Disposable;
import forge.adventure.util.Config;
/**
* Base class for all rendered scenes
*/
public abstract class Scene implements Disposable {
public Scene() {
}
public static int GetIntendedWidth() {
return Config.instance().getConfigData().screenWidth;
}
public static int GetIntendedHeight() {
return Config.instance().getConfigData().screenHeight;
}
public abstract void act(float delta);
public abstract void render();
public void create() {
}
public Drawable DrawableImage(String path) {
return new TextureRegionDrawable(new Texture(Config.instance().getFile(path)));
}
public void resLoaded() {
}
public boolean leave() {
return true;
}
public void enter() {
}
}

View File

@@ -0,0 +1,23 @@
package forge.adventure.scene;
/**
* Enum of all scenes
*/
public enum SceneType {
StartScene(new forge.adventure.scene.StartScene()),
NewGameScene(new forge.adventure.scene.NewGameScene()),
SettingsScene(new forge.adventure.scene.SettingsScene()),
GameScene(new forge.adventure.scene.GameScene()),
DuelScene(new forge.adventure.scene.DuelScene()),
SaveLoadScene(new forge.adventure.scene.SaveLoadScene()),
DeckEditScene(new forge.adventure.scene.DeckEditScene()),
TileMapScene(new forge.adventure.scene.TileMapScene()),
RewardScene(new forge.adventure.scene.RewardScene()),
InnScene(new forge.adventure.scene.InnScene());
public final forge.adventure.scene.Scene instance;
SceneType(forge.adventure.scene.Scene scene) {
this.instance = scene;
}
}

View File

@@ -0,0 +1,194 @@
package forge.adventure.scene;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Align;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.util.Config;
import forge.adventure.util.Controls;
import forge.localinstance.properties.ForgePreferences;
import forge.util.Localizer;
import java.util.function.Function;
/**
* Scene to handle settings of the base forge and adventure mode
*/
public class SettingsScene extends UIScene {
static public ForgePreferences Preference;
Stage stage;
Texture Background;
private Table settingGroup;
public SettingsScene() {
super("ui/settings.json");
}
@Override
public void dispose() {
if (stage != null)
stage.dispose();
}
public void renderAct(float delta) {
Gdx.gl.glClearColor(1, 0, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.getBatch().begin();
stage.getBatch().disableBlending();
stage.getBatch().draw(Background, 0, 0, GetIntendedWidth(), GetIntendedHeight());
stage.getBatch().enableBlending();
stage.getBatch().end();
stage.act(delta);
stage.draw();
}
public boolean back() {
AdventureApplicationAdapter.instance.switchToLast();
return true;
}
private void addCheckBox(String name, ForgePreferences.FPref pref) {
CheckBox box = Controls.newCheckBox("");
box.setChecked(Preference.getPrefBoolean(pref));
box.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
Preference.setPref(pref, ((CheckBox) actor).isChecked());
Preference.save();
}
});
addLabel(name);
settingGroup.add(box).align(Align.right);
}
private void addSettingSlider(String name, ForgePreferences.FPref pref, int min,int max) {
Slider slide = Controls.newSlider(min,max, 1, false);
slide.setValue(Preference.getPrefInt(pref));
slide.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
Preference.setPref(pref, String.valueOf((int) ((Slider) actor).getValue()));
Preference.save();
}
});
addLabel(name);
settingGroup.add(slide).align(Align.right);
}
private void addSettingField(String name, boolean value, ChangeListener change) {
CheckBox box = Controls.newCheckBox("");
box.setChecked(value);
box.addListener(change);
addLabel(name);
settingGroup.add(box).align(Align.right);
}
private void addSettingField(String name, int value, ChangeListener change) {
TextField text = Controls.newTextField(String.valueOf(value));
text.setTextFieldFilter(new TextField.TextFieldFilter() {
@Override
public boolean acceptChar(TextField textField, char c) {
return Character.isDigit(c);
}
});
text.addListener(change);
addLabel(name);
settingGroup.add(text).align(Align.right);
}
void addLabel( String name)
{
Label label = new Label(name, Controls.GetSkin().get("white",Label.LabelStyle.class));
settingGroup.row().space(5);
settingGroup.add(label).align(Align.left).fillX();
}
@Override
public void resLoaded() {
super.resLoaded();
settingGroup = new Table();
if (Preference == null) {
Preference = new ForgePreferences();
}
Localizer localizer = Localizer.getInstance();
SelectBox plane = Controls.newComboBox(Config.instance().getAllAdventures(), Config.instance().getSettingData().plane, new Function<Object, Void>() {
@Override
public Void apply(Object o) {
Config.instance().getSettingData().plane= (String) o;
Config.instance().saveSettings();
return null;
}
});
addLabel("Plane");
settingGroup.add(plane).align(Align.right);
addSettingField("Fullscreen", Config.instance().getSettingData().fullScreen, new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
Config.instance().getSettingData().fullScreen=((CheckBox) actor).isChecked();
Config.instance().saveSettings();
}
});
addSettingField("Screen width", Config.instance().getSettingData().width, new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
String text=((TextField) actor).getText();
Config.instance().getSettingData().width=text==null||text.isEmpty()?0:Integer.valueOf(text);
Config.instance().saveSettings();
}
});
addSettingField("Screen height", Config.instance().getSettingData().height, new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
String text=((TextField) actor).getText();
Config.instance().getSettingData().height=text==null||text.isEmpty()?0:Integer.valueOf(text);
Config.instance().saveSettings();
}
});
addCheckBox(localizer.getMessage("lblCardName"), ForgePreferences.FPref.UI_OVERLAY_CARD_NAME);
addSettingSlider(localizer.getMessage("cbAdjustMusicVolume"), ForgePreferences.FPref.UI_VOL_MUSIC,0,100);
addSettingSlider(localizer.getMessage("cbAdjustSoundsVolume"), ForgePreferences.FPref.UI_VOL_SOUNDS, 0,100);
addCheckBox(localizer.getMessage("lblManaCost"), ForgePreferences.FPref.UI_OVERLAY_CARD_MANA_COST);
addCheckBox(localizer.getMessage("lblPowerOrToughness"), ForgePreferences.FPref.UI_OVERLAY_CARD_POWER);
addCheckBox(localizer.getMessage("lblCardID"), ForgePreferences.FPref.UI_OVERLAY_CARD_ID);
addCheckBox(localizer.getMessage("lblAbilityIcon"), ForgePreferences.FPref.UI_OVERLAY_ABILITY_ICONS);
addCheckBox(localizer.getMessage("cbImageFetcher"), ForgePreferences.FPref.UI_ENABLE_ONLINE_IMAGE_FETCHER);
settingGroup.row();
ui.onButtonPress("return", () -> back());
ScrollPane scrollPane = ui.findActor("settings");
scrollPane.setActor(settingGroup);
}
@Override
public void create() {
}
enum ControlTypes {
CheckBox,
Slider,
Resolution
}
}

View File

@@ -0,0 +1,87 @@
package forge.adventure.scene;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Actor;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.world.WorldSave;
/**
* First scene after the splash screen
*/
public class StartScene extends UIScene {
Actor saveButton;
Actor resumeButton;
public StartScene()
{
super("ui/start_menu.json");
}
public boolean NewGame() {
AdventureApplicationAdapter.instance.switchScene(SceneType.NewGameScene.instance);
return true;
}
public boolean Save() {
((SaveLoadScene) SceneType.SaveLoadScene.instance).setSaveGame(true);
AdventureApplicationAdapter.instance.switchScene(SceneType.SaveLoadScene.instance);
return true;
}
public boolean Load() {
((SaveLoadScene) SceneType.SaveLoadScene.instance).setSaveGame(false);
AdventureApplicationAdapter.instance.switchScene(SceneType.SaveLoadScene.instance);
return true;
}
public boolean Resume() {
AdventureApplicationAdapter.instance.switchToLast();
return true;
}
public boolean settings() {
AdventureApplicationAdapter.instance.switchScene(forge.adventure.scene.SceneType.SettingsScene.instance);
return true;
}
public boolean Exit() {
Gdx.app.exit();
System.exit(0);
return true;
}
@Override
public void enter() {
saveButton.setVisible(WorldSave.getCurrentSave().getWorld().getData() != null);
resumeButton.setVisible(WorldSave.getCurrentSave().getWorld().getData() != null);
Gdx.input.setInputProcessor(stage); //Start taking input from the ui
}
@Override
public void create() {
}
@Override
public void resLoaded() {
super.resLoaded();
ui.onButtonPress("Start", () -> NewGame());
ui.onButtonPress("Load", () -> Load());
ui.onButtonPress("Start", () -> NewGame());
ui.onButtonPress("Save", () -> Save());
ui.onButtonPress("Resume", () -> Resume());
saveButton = ui.findActor("Save");
resumeButton = ui.findActor("Resume");
ui.onButtonPress("Settings", () -> settings());
ui.onButtonPress("Exit", () -> Exit());
saveButton.setVisible(false);
resumeButton.setVisible(false);
}
}

View File

@@ -0,0 +1,91 @@
package forge.adventure.scene;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.maps.tiled.TiledMap;
import forge.adventure.stage.MapStage;
import forge.adventure.stage.PointOfInterestMapRenderer;
import forge.adventure.util.Config;
import forge.adventure.util.TemplateTmxMapLoader;
import forge.adventure.world.PointOfInterest;
import forge.adventure.world.WorldSave;
/**
* Scene that will render tiled maps.
* Used for towns dungeons etc
*
*/
public class TileMapScene extends HudScene {
TiledMap map;
PointOfInterestMapRenderer tiledMapRenderer;
private String nextMap;
public TileMapScene() {
super(MapStage.getInstance());
tiledMapRenderer = new PointOfInterestMapRenderer((MapStage)stage);
}
@Override
public void dispose() {
if (map != null)
map.dispose();
}
@Override
public void act(float delta)
{
if(map==null)
return;
if(nextMap!=null)
{
load(nextMap);
nextMap=null;
}
stage.act(Gdx.graphics.getDeltaTime());
}
@Override
public void render()
{
if(map==null)
return;
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
tiledMapRenderer.setView(stage.getCamera().combined, 0, 0, Scene.GetIntendedWidth(), Scene.GetIntendedHeight());
tiledMapRenderer.render();
hud.draw();
}
public void load(PointOfInterest point) {
rootPoint=point;
oldMap=point.getData().map;
map = new TemplateTmxMapLoader().load(Config.instance().getFilePath(point.getData().map));
((MapStage)stage).setPointOfInterest(WorldSave.getCurrentSave().getPointOfInterestChanges(point.getID()+oldMap));
stage.GetPlayer().setPosition(0, 0);
WorldSave.getCurrentSave().getWorld().setSeed(point.getSeedOffset());
tiledMapRenderer.loadMap(map,"");
}
PointOfInterest rootPoint;
String oldMap;
private void load(String targetMap) {
map = new TemplateTmxMapLoader().load(Config.instance().getFilePath(targetMap));
((MapStage)stage).setPointOfInterest(WorldSave.getCurrentSave().getPointOfInterestChanges(rootPoint.getID()+targetMap));
stage.GetPlayer().setPosition(0, 0);
WorldSave.getCurrentSave().getWorld().setSeed(rootPoint.getSeedOffset());
tiledMapRenderer.loadMap(map,oldMap);
oldMap=targetMap;
}
public void loadNext(String targetMap) {
nextMap=targetMap;
}
}

View File

@@ -0,0 +1,84 @@
package forge.adventure.scene;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.viewport.StretchViewport;
import forge.adventure.util.Config;
import forge.adventure.util.UIActor;
/**
* Base class for an GUI scene where the elements are loaded from a json file
*/
public class UIScene extends Scene{
protected UIActor ui;
Stage stage;
String uiFile;
public UIScene(String uiFilePath) {
uiFile=uiFilePath;
}
@Override
public void dispose() {
if(stage!=null)
stage.dispose();
}
@Override
public void act(float delta) {
stage.act(delta);
}
@Override
public void render() {
Gdx.gl.glClearColor(0, 0, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.draw();
}
public UIActor getUI()
{
return ui;
}
@Override
public void resLoaded() {
stage = new Stage(new StretchViewport(GetIntendedWidth(), GetIntendedHeight()));
ui = new UIActor(Config.instance().getFile(uiFile));
screenImage=ui.findActor("lastScreen");
stage.addActor(ui);
}
Image screenImage;
TextureRegion backgroundTexture;
@Override
public void enter() {
Gdx.input.setInputProcessor(stage); //Start taking input from the ui
if(screenImage!=null)
{
if (backgroundTexture != null)
backgroundTexture.getTexture().dispose();
final Pixmap pixmap = Pixmap.createFromFrameBuffer(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
final Pixmap potPixmap = new Pixmap(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), Pixmap.Format.RGBA8888);
potPixmap.setBlending(Pixmap.Blending.SourceOver);
potPixmap.drawPixmap(pixmap, 0, 0);
potPixmap.setColor(0,0,0,0.75f);
potPixmap.fillRectangle(0,0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
backgroundTexture = new TextureRegion(new Texture(potPixmap), 0, Gdx.graphics.getHeight(), Gdx.graphics.getWidth(), -Gdx.graphics.getHeight());
screenImage.setDrawable(new TextureRegionDrawable(backgroundTexture));
}
super.enter();
}
}

View File

@@ -0,0 +1,118 @@
package forge.adventure.stage;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.viewport.FitViewport;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.scene.Scene;
import forge.adventure.scene.SceneType;
import forge.adventure.util.Current;
import forge.adventure.util.Config;
import forge.adventure.util.UIActor;
import forge.adventure.world.AdventurePlayer;
import forge.adventure.world.WorldSave;
/**
* Stage to handle everything rendered in the HUD
*/
public class GameHUD extends Stage {
static public GameHUD instance;
private final GameStage gameStage;
private final Image avatar;
private final Image miniMapPlayer;
private final Label lifePoints;
private final Label money;
private Image miniMap;
private GameHUD(GameStage gameStage) {
super(new FitViewport(Scene.GetIntendedWidth(), Scene.GetIntendedHeight()), gameStage.getBatch());
instance = this;
this.gameStage = gameStage;
UIActor ui = new UIActor(Config.instance().getFile("ui/hud.json"));
miniMap = ui.findActor("map");
Pixmap player = new Pixmap(3, 3, Pixmap.Format.RGB888);
player.setColor(1.0f, 0.0f, 0.0f, 1.0f);
player.fill();
miniMapPlayer = new Image(new Texture(player));
avatar = ui.findActor("avatar");
ui.onButtonPress("menu", () -> menu());
ui.onButtonPress("deck", () -> openDeck());
lifePoints = ui.findActor("lifePoints");
lifePoints.setText("20/20");
AdventurePlayer.current().onLifeChange(()-> lifePoints.setText(AdventurePlayer.current().getLife() +"/"+ AdventurePlayer.current().getMaxLife()));
money = ui.findActor("money");
WorldSave.getCurrentSave().getPlayer().onGoldChange(()-> money.setText(String.valueOf(AdventurePlayer.current().getGold()))) ;
miniMap = ui.findActor("map");
addActor(ui);
addActor(miniMapPlayer);
}
public static GameHUD getInstance() {
return instance == null ? instance = new GameHUD(WorldStage.getInstance()) : instance;
}
@Override
public boolean touchDown (int screenX, int screenY, int pointer, int button)
{
Vector2 c=new Vector2();
screenToStageCoordinates(c.set(screenX, screenY));
float x=(c.x-miniMap.getX())/miniMap.getWidth();
float y=(c.y-miniMap.getY())/miniMap.getHeight();
if(x>=0&&x<=1.0&&y>=0&&y<=1.0)
{
WorldStage.getInstance().GetPlayer().setPosition(x*WorldSave.getCurrentSave().getWorld().getWidthInPixels(),y*WorldSave.getCurrentSave().getWorld().getHeightInPixels());
return true;
}
return super.touchDown(screenX,screenY, pointer,button);
}
@Override
public void draw() {
int yPos = (int) gameStage.player.getY();
int xPos = (int) gameStage.player.getX();
act(Gdx.graphics.getDeltaTime()); //act the Hud
super.draw(); //draw the Hud
int xPosMini = (int) (((float) xPos / (float) WorldSave.getCurrentSave().getWorld().getTileSize() / (float) WorldSave.getCurrentSave().getWorld().getWidthInTiles()) * miniMap.getWidth());
int yPosMini = (int) (((float) yPos / (float) WorldSave.getCurrentSave().getWorld().getTileSize() / (float) WorldSave.getCurrentSave().getWorld().getHeightInTiles()) * miniMap.getHeight());
miniMapPlayer.setPosition(miniMap.getX() + xPosMini - 1, miniMap.getY() + yPosMini - 1);
}
Texture miniMapTexture;
public void enter() {
if(miniMapTexture==null)
{
miniMapTexture=new Texture(WorldSave.getCurrentSave().getWorld().getBiomeImage());
}
miniMap.setDrawable(new TextureRegionDrawable(miniMapTexture));
avatar.setDrawable(new TextureRegionDrawable(Current.player().avatar()));
}
private Object openDeck() {
AdventureApplicationAdapter.instance.switchScene(SceneType.DeckEditScene.instance);
return null;
}
private Object menu() {
gameStage.openMenu();
return null;
}
}

View File

@@ -0,0 +1,334 @@
package forge.adventure.stage;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.StretchViewport;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.character.MapActor;
import forge.adventure.character.PlayerSprite;
import forge.adventure.scene.Scene;
import forge.adventure.scene.SceneType;
import forge.adventure.world.WorldSave;
import forge.adventure.world.WorldSaveHeader;
/**
* Base class to render a player sprite on a map
* used for the over world and dungeons
*/
public abstract class GameStage extends Stage {
private final OrthographicCamera camera;
Group backgroundSprites;
SpriteGroup foregroundSprites;
PlayerSprite player;
private float touchX = -1;
private float touchY = -1;
private final float timer = 0;
private float animationTimeout = 0;
public void startPause(int i) {
startPause(i,null);
}
public void startPause(int i,Runnable runnable) {
onEndAction=runnable;
animationTimeout=i;
player.setMovementDirection(Vector2.Zero);
}
public boolean isPaused() {
return animationTimeout>0;
}
public GameStage() {
super(new StretchViewport(Scene.GetIntendedWidth(), Scene.GetIntendedHeight(), new OrthographicCamera()));
camera = (OrthographicCamera) getCamera();
backgroundSprites = new Group();
foregroundSprites = new SpriteGroup();
addActor(backgroundSprites);
addActor(foregroundSprites);
}
public void setWinner(boolean b) {
}
public void setBounds(float width, float height) {
getViewport().setWorldSize(width, height);
}
public PlayerSprite GetPlayer() {
if (player == null) {
player = new PlayerSprite(this);
foregroundSprites.addActor(player);
}
return player;
}
public SpriteGroup GetSpriteGroup() {
return foregroundSprites;
}
public Group GetBackgroundSprites() {
return backgroundSprites;
}
Runnable onEndAction;
@Override
public final void act(float delta) {
super.act(delta);
if (animationTimeout >= 0) {
animationTimeout -= delta;
return;
}
if(isPaused())
{
return;
}
if (onEndAction != null) {
onEndAction.run();
onEndAction=null;
}
if (touchX >= 0) {
Vector2 target = this.screenToStageCoordinates(new Vector2(touchX, touchY));
target.x -= player.getWidth() / 2f;
Vector2 diff = target.sub(player.pos());
if (diff.len() < 2) {
diff.setZero();
player.stop();
}
player.setMovementDirection(diff);
}
//debug speed up
/*
if (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT))
player.setMoveModifier(20);
else
player.setMoveModifier(1);*/
camera.position.x = Math.min(Math.max(Scene.GetIntendedWidth() / 2f, player.pos().x), getViewport().getWorldWidth() - Scene.GetIntendedWidth() / 2f);
camera.position.y = Math.min(Math.max(Scene.GetIntendedHeight() / 2f, player.pos().y), getViewport().getWorldHeight() - Scene.GetIntendedHeight() / 2f);
onActing(delta);
}
abstract protected void onActing(float delta);
@Override
public boolean keyDown(int keycode) {
super.keyDown(keycode);
if (keycode == Input.Keys.LEFT || keycode == Input.Keys.A)//todo config
{
player.getMovementDirection().x = -1;
}
if (keycode == Input.Keys.RIGHT || keycode == Input.Keys.D)//todo config
{
player.getMovementDirection().x = +1;
}
if (keycode == Input.Keys.UP || keycode == Input.Keys.W)//todo config
{
player.getMovementDirection().y = +1;
}
if (keycode == Input.Keys.DOWN || keycode == Input.Keys.S)//todo config
{
player.getMovementDirection().y = -1;
}
if (keycode == Input.Keys.F12)
{
debugCollision(true);
for (Actor actor : foregroundSprites.getChildren()) {
if (actor instanceof MapActor) {
((MapActor)actor).setBoundDebug(true);
}
}
player.setBoundDebug(true);
}
if (keycode == Input.Keys.F11)
{
debugCollision(false);
for (Actor actor : foregroundSprites.getChildren()) {
if (actor instanceof MapActor) {
((MapActor)actor).setBoundDebug(false);
}
}
player.setBoundDebug(false);
}
if (keycode == Input.Keys.F10)
{
setDebugAll(true);
}
if (keycode == Input.Keys.F9)
{
setDebugAll(false);
}
return true;
}
protected void debugCollision(boolean b) {
}
@Override
public boolean scrolled(float amountX, float amountY) {
if(isPaused())
return true;
camera.zoom += (amountY * 0.03);
if (camera.zoom < 0.2f)
camera.zoom = 0.2f;
if (camera.zoom > 1.5f)
camera.zoom = 1.5f;
return super.scrolled(amountX, amountY);
}
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
if(isPaused())
return true;
touchX = screenX;
touchY = screenY;
return false;
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
if(isPaused())
return true;
touchX = screenX;
touchY = screenY;
return true;
}
public void stop() {
touchX = -1;
touchY = -1;
player.stop();
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
stop();
return true;
}
@Override
public boolean keyUp(int keycode) {
if(isPaused())
return true;
if (keycode == Input.Keys.LEFT || keycode == Input.Keys.A || keycode == Input.Keys.RIGHT || keycode == Input.Keys.D)//todo config
{
player.getMovementDirection().x = 0;
if(!player.isMoving())
stop();
}
if (keycode == Input.Keys.UP || keycode == Input.Keys.W || keycode == Input.Keys.DOWN || keycode == Input.Keys.S)//todo config
{
player.getMovementDirection().y = 0;
if(!player.isMoving())
stop();
}
if (keycode == Input.Keys.ESCAPE) {
openMenu();
}
return false;
}
public void openMenu() {
Pixmap pixmap = Pixmap.createFromFrameBuffer(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Pixmap scaled = new Pixmap(WorldSaveHeader.previewImageWidth, (int) (WorldSaveHeader.previewImageWidth / (Scene.GetIntendedWidth() / (float) Scene.GetIntendedHeight())), Pixmap.Format.RGB888);
scaled.drawPixmap(pixmap,
0, 0, pixmap.getWidth(), pixmap.getHeight(),
0, 0, scaled.getWidth(), scaled.getHeight());
pixmap.dispose();
if (WorldSave.getCurrentSave().header.preview != null)
WorldSave.getCurrentSave().header.preview.dispose();
WorldSave.getCurrentSave().header.preview = scaled;
AdventureApplicationAdapter.instance.switchScene(SceneType.StartScene.instance);
}
public void enter() {
stop();
}
public void leave() {
stop();
}
public boolean isColliding(Rectangle boundingRect)
{
return false;
}
public void prepareCollision(Vector2 pos, Vector2 direction, Rectangle boundingRect)
{
}
public Vector2 adjustMovement( Vector2 direction, Rectangle boundingRect)
{
Vector2 adjDirX=direction.cpy();
Vector2 adjDirY=direction.cpy();
boolean foundX=false;
boolean foundY=false;
while(true)
{
if(!isColliding(new Rectangle(boundingRect.x+adjDirX.x,boundingRect.y+adjDirX.y, boundingRect.width, boundingRect.height)))
{
foundX=true;
break;
}
if(adjDirX.x==0)
break;
if(adjDirX.x>=0)
adjDirX.x=Math.round(Math.max(0,adjDirX.x-1));
else
adjDirX.x=Math.round(Math.max(0,adjDirX.x+1));
}
while(true)
{
if(!isColliding(new Rectangle(boundingRect.x+adjDirY.x,boundingRect.y+adjDirY.y, boundingRect.width, boundingRect.height)))
{
foundY=true;
break;
}
if(adjDirY.y==0)
break;
if(adjDirY.y>=0)
adjDirY.y=Math.round(Math.max(0,adjDirY.y-1));
else
adjDirY.y=Math.round(Math.max(0,adjDirY.y+1));
}
if(foundY&&foundX)
return adjDirX.len()>adjDirY.len()?adjDirX:adjDirY;
else if(foundY)
return adjDirY;
else if(foundX)
return adjDirX;
return Vector2.Zero.cpy();
}
}

View File

@@ -0,0 +1,77 @@
package forge.adventure.stage;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import forge.adventure.data.BiomeSpriteData;
import forge.adventure.world.PointOfInterest;
import forge.adventure.world.WorldSave;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.List;
/**
* Sprite actor that will render trees and rocks on the over world
*/
public class MapSprite extends Actor {
static public int BackgroundLayer = -1;
static public int SpriteLayer = 0;
TextureRegion texture;
public MapSprite(Vector2 pos, TextureRegion sprite) {
texture = sprite;
setPosition(pos.x, pos.y);
setHeight(texture.getRegionHeight());
setWidth(texture.getRegionWidth());
}
public static ArrayList<Actor> GetMapSprites(int chunkX, int chunkY) {
ArrayList<Actor> actorGroup = new ArrayList<>();
List<PointOfInterest> pointsOfInterest = WorldSave.getCurrentSave().getWorld().getPointsOfInterest(chunkX, chunkY);
for (PointOfInterest poi : pointsOfInterest) {
Actor sprite = new PointOfInterestMapSprite(poi);
actorGroup.add(sprite);
}
List<Pair<Vector2, Integer>> objects = WorldSave.getCurrentSave().getWorld().GetMapObjects(chunkX, chunkY);
for (Pair<Vector2, Integer> entry : objects) {
BiomeSpriteData data = WorldSave.getCurrentSave().getWorld().getObject(entry.getValue());
if (data.layer != SpriteLayer)
continue;
Actor sprite = new MapSprite(entry.getKey(), WorldSave.getCurrentSave().getWorld().getData().GetBiomeSprites().getSprite(data.name, (int) entry.getKey().x + (int) entry.getKey().y * 11483));
actorGroup.add(sprite);
}
return actorGroup;
}
public static ArrayList<Actor> GetMapSpritesBackground(int chunkX, int chunkY) {
List<Pair<Vector2, Integer>> objects = WorldSave.getCurrentSave().getWorld().GetMapObjects(chunkX, chunkY);
ArrayList<Actor> actorGroup = new ArrayList<>();
for (Pair<Vector2, Integer> entry : objects) {
BiomeSpriteData data = WorldSave.getCurrentSave().getWorld().getObject(entry.getValue());
if (data.layer != BackgroundLayer)
continue;
Actor sprite = new MapSprite(entry.getKey(), WorldSave.getCurrentSave().getWorld().getData().GetBiomeSprites().getSprite(data.name, (int) entry.getKey().x + (int) entry.getKey().y * 11483));
actorGroup.add(sprite);
}
return actorGroup;
}
//BitmapFont font;
@Override
public void draw(Batch batch, float parentAlpha) {
if (texture == null)
return;
batch.draw(texture, getX(), getY());
//font.draw(batch,String.valueOf(getZIndex()),getX()-(getWidth()/2),getY());
}
}

View File

@@ -0,0 +1,368 @@
package forge.adventure.stage;
import com.badlogic.gdx.maps.MapLayer;
import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.MapProperties;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.utils.Array;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.character.*;
import forge.adventure.data.RewardData;
import forge.adventure.data.ShopData;
import forge.adventure.data.WorldData;
import forge.adventure.scene.DuelScene;
import forge.adventure.scene.RewardScene;
import forge.adventure.scene.SceneType;
import forge.adventure.util.Config;
import forge.adventure.util.Reward;
import forge.adventure.world.PointOfInterestChanges;
import forge.adventure.world.WorldSave;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Stage to handle tiled maps for points of interests
*/
public class MapStage extends GameStage {
public static MapStage instance;
Array<MapActor> actors = new Array<>();
TiledMap map;
ArrayList<Rectangle>[][] collision;
private float tileHeight;
private float tileWidth;
private float width;
private float height;
MapLayer spriteLayer;
private PointOfInterestChanges changes;
private EnemySprite currentMob;
private final Vector2 oldPosition=new Vector2();//todo
private final Vector2 oldPosition2=new Vector2();
private final Vector2 oldPosition3=new Vector2();
private final Vector2 oldPosition4=new Vector2();
public MapLayer getSpriteLayer()
{
return spriteLayer;
}
public PointOfInterestChanges getChanges()
{
return changes;
}
public static MapStage getInstance() {
return instance == null ? instance = new MapStage() : instance;
}
public void addMapActor(MapObject obj, MapActor newActor) {
newActor.setWidth(Float.parseFloat(obj.getProperties().get("width").toString()));
newActor.setHeight(Float.parseFloat(obj.getProperties().get("height").toString()));
newActor.setX(Float.parseFloat(obj.getProperties().get("x").toString()));
newActor.setY(Float.parseFloat(obj.getProperties().get("y").toString()));
actors.add(newActor);
foregroundSprites.addActor(newActor);
}
public void addMapActor(MapActor newActor) {
actors.add(newActor);
foregroundSprites.addActor(newActor);
}
@Override
public boolean isColliding( Rectangle adjustedBoundingRect)
{
for(Rectangle collision:currentCollidingRectangles)
{
if(collision.overlaps(adjustedBoundingRect))
{
return true;
}
}
return false;
}
final ArrayList<Rectangle> currentCollidingRectangles=new ArrayList<>();
@Override
public void prepareCollision(Vector2 pos, Vector2 direction, Rectangle boundingRect)
{
currentCollidingRectangles.clear();
int x1= (int) (Math.min(boundingRect.x,boundingRect.x+direction.x)/tileWidth);
int y1= (int) (Math.min(boundingRect.y,boundingRect.y+direction.y)/tileHeight);
int x2= (int) (Math.min(boundingRect.x+boundingRect.width,boundingRect.x+boundingRect.width+direction.x)/tileWidth);
int y2= (int) (Math.min(boundingRect.y+boundingRect.height,boundingRect.y+boundingRect.height+direction.y)/tileHeight);
for(int x=x1;x<=x2;x++)
{
for(int y=y1;y<=y2;y++)
{
if(x<0||x>=width||y<0||y>=height)
{
continue;
}
currentCollidingRectangles.addAll(collision[x][y]);
}
}
}
Group collisionGroup;
@Override
protected void debugCollision(boolean b) {
if(collisionGroup==null)
{
collisionGroup=new Group();
for (int x = 0; x < collision.length; x++)
{
for (int y = 0; y < collision[x].length; y++)
{
for(Rectangle rectangle:collision[x][y])
{
MapActor collisionActor=new MapActor();
collisionActor.setBoundDebug(true);
collisionActor.setWidth(rectangle.width);
collisionActor.setHeight(rectangle.height);
collisionActor.setX(rectangle.x);
collisionActor.setY(rectangle.y);
collisionGroup.addActor(collisionActor);
}
}
}
}
if(b)
{
addActor(collisionGroup);
}
else
{
collisionGroup.remove();
}
}
public void loadMap(TiledMap map,String sourceMap) {
this.map=map;
for (MapActor actor : new Array.ArrayIterator<>(actors)) {
actor.remove();
foregroundSprites.removeActor(actor);
}
actors = new Array<>();
width = Float.parseFloat(map.getProperties().get("width").toString());
height = Float.parseFloat(map.getProperties().get("height").toString());
tileHeight = Float.parseFloat(map.getProperties().get("tileheight").toString());
tileWidth = Float.parseFloat(map.getProperties().get("tilewidth").toString());
setBounds(width * tileWidth, height * tileHeight);
collision= new ArrayList[(int) width][(int) height];
GetPlayer().stop();
for(MapLayer layer: map.getLayers())
{
if(layer.getProperties().containsKey("spriteLayer")&&layer.getProperties().get("spriteLayer",boolean.class))
{
spriteLayer=layer;
}
if(layer instanceof TiledMapTileLayer)
{
loadCollision((TiledMapTileLayer)layer);
}
else
{
loadObjects(layer,sourceMap);
}
}
}
private void loadCollision(TiledMapTileLayer layer) {
for(int x=0;x<layer.getWidth();x++)
{
for(int y=0;y<layer.getHeight();y++)
{
if(collision[x][y]==null)
collision[x][y]=new ArrayList<>();
ArrayList<Rectangle> map=collision[x][y];
TiledMapTileLayer.Cell cell=layer.getCell(x,y);
if(cell==null)
continue;
for(MapObject collision:cell.getTile().getObjects())
{
if(collision instanceof RectangleMapObject)
{
Rectangle r=((RectangleMapObject)collision).getRectangle();
map.add(new Rectangle((Math.round(layer.getTileWidth()*x)+r.x),(Math.round(layer.getTileHeight()*y)+r.y),Math.round(r.width),Math.round(r.height)));
}
}
}
}
}
private void loadObjects(MapLayer layer,String sourceMap) {
player.setMoveModifier(2);
for (MapObject obj : layer.getObjects()) {
MapProperties prop=obj.getProperties();
Object typeObject = prop.get("type");
if (typeObject != null) {
String type = prop.get("type",String.class);
int id = prop.get("id",int.class);
if(changes.isObjectDeleted(id))
continue;
switch (type) {
case "entry":
float x=Float.parseFloat(prop.get("x").toString());
float y=Float.parseFloat(prop.get("y").toString());
float w=Float.parseFloat(prop.get("width").toString());
float h=Float.parseFloat(prop.get("height").toString());
EntryActor entry=new EntryActor(this,sourceMap,id,prop.get("teleport").toString(),x,y,w,h,prop.get("direction").toString());
addMapActor(obj, entry);
break;
case "enemy":
EnemySprite mob=new EnemySprite(id, WorldData.getEnemy(prop.get("enemy").toString()));
addMapActor(obj, mob);
break;
case "inn":
addMapActor(obj, new OnCollide(() -> AdventureApplicationAdapter.instance.switchScene(SceneType.InnScene.instance)));
break;
case "exit":
addMapActor(obj, new OnCollide(() -> exit()));
break;
case "shop":
String shopList=prop.get("shopList").toString();
List possibleShops=Arrays.asList(shopList.split(","));
Array<ShopData> shops;
if(possibleShops.size()==0||shopList.equals(""))
shops= WorldData.getShopList();
else
{
shops=new Array<>();
for(ShopData data:new Array.ArrayIterator<>(WorldData.getShopList()))
{
if(possibleShops.contains(data.name))
{
shops.add(data);
}
}
}
if(shops.size==0)
continue;
ShopData data=shops.get(WorldSave.getCurrentSave().getWorld().getRandom().nextInt(shops.size));
Array<Reward> ret=new Array<Reward>();
for(RewardData rdata:new Array.ArrayIterator<>(data.rewards))
{
ret.addAll(rdata.generate(false));
}
ShopActor actor=new ShopActor(this,id,ret);
addMapActor(obj,actor);
if(prop.containsKey("signYOffset")&&prop.containsKey("signXOffset"))
{
try {
TextureSprite sprite=new TextureSprite(Config.instance().getAtlas(data.spriteAtlas).createSprite(data.sprite));
sprite.setX(actor.getX()+Float.parseFloat(prop.get("signXOffset").toString()));
sprite.setY(actor.getY()+Float.parseFloat(prop.get("signYOffset").toString()));
addMapActor(sprite);
}
catch (Exception e)
{
System.err.print("Can not create Texture for "+data.sprite+" Obj:"+data);
}
}
break;
}
}
}
}
public boolean exit() {
AdventureApplicationAdapter.instance.switchScene(SceneType.GameScene.instance);
return true;
}
@Override
public void setWinner(boolean playerWins) {
if (playerWins) {
player.setAnimation(CharacterSprite.AnimationTypes.Attack);
currentMob.setAnimation(CharacterSprite.AnimationTypes.Death);
startPause(1,()->getReward());
} else {
player.setAnimation(CharacterSprite.AnimationTypes.Hit);
currentMob.setAnimation(CharacterSprite.AnimationTypes.Attack);
startPause(1,()->
{
player.setAnimation(CharacterSprite.AnimationTypes.Idle);
currentMob.setAnimation(CharacterSprite.AnimationTypes.Idle);
player.setPosition(oldPosition4);
stop();
currentMob=null;
});
}
}
protected void getReward()
{
((RewardScene)SceneType.RewardScene.instance).loadRewards(currentMob.getRewards(), RewardScene.Type.Loot, null);
currentMob.remove();
actors.removeValue(currentMob,true);
changes.deleteObject(currentMob.getId());
currentMob = null;
AdventureApplicationAdapter.instance.switchScene(SceneType.RewardScene.instance);
}
@Override
protected void onActing(float delta) {
oldPosition4.set(oldPosition3);
oldPosition3.set(oldPosition2);
oldPosition2.set(oldPosition);
oldPosition.set(player.pos());
for (MapActor actor : new Array.ArrayIterator<>(actors)) {
if (actor.collideWithPlayer(player)) {
if(actor instanceof EnemySprite)
{
EnemySprite mob=(EnemySprite) actor;
currentMob=mob;
if(mob.getData().deck==null||mob.getData().deck.isEmpty())
{
currentMob.setAnimation(CharacterSprite.AnimationTypes.Death);
startPause(1,()->getReward());
}
else
{
player.setAnimation(CharacterSprite.AnimationTypes.Attack);
mob.setAnimation(CharacterSprite.AnimationTypes.Attack);
startPause(1,()->
{
((DuelScene) SceneType.DuelScene.instance).setEnemy(mob);
((DuelScene) SceneType.DuelScene.instance).setPlayer(player);
AdventureApplicationAdapter.instance.switchScene(SceneType.DuelScene.instance);
});
}
}
}
}
}
public void setPointOfInterest(PointOfInterestChanges change) {
changes =change;
}
}

View File

@@ -0,0 +1,40 @@
package forge.adventure.stage;
import com.badlogic.gdx.maps.MapLayer;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
/**
* Custom renderer to render the game stage between the map layers of a tiled map
*/
public class PointOfInterestMapRenderer extends OrthogonalTiledMapRenderer {
private final MapStage stage;
public PointOfInterestMapRenderer(MapStage stage) {
super(null,stage.getBatch());
this.stage = stage;
}
@Override
public void render () {
beginRender();
for (MapLayer layer : map.getLayers()) {
renderMapLayer(layer);
if(layer==stage.getSpriteLayer())
{
//end render to draw character sprites
batch.end();
stage.draw();
batch.begin();
}
}
endRender();
}
public void loadMap(TiledMap map,String sourceMap)
{
stage.loadMap(map,sourceMap);
super.setMap(map);
}
}

View File

@@ -0,0 +1,48 @@
package forge.adventure.stage;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Rectangle;
import forge.adventure.world.PointOfInterest;
/**
* MapSprite for points of interest to add a bounding rect for collision detection
*/
public class PointOfInterestMapSprite extends MapSprite {
PointOfInterest pointOfInterest;
Texture debugTexture;
Rectangle boundingRect;
public PointOfInterestMapSprite(PointOfInterest point) {
super(point.getPosition(), point.getSprite());
pointOfInterest = point;
boundingRect = new Rectangle(getX(), getY(), texture.getRegionWidth(), texture.getRegionHeight());
}
public PointOfInterest getPointOfInterest() {
return pointOfInterest;
}
private Texture getDebugTexture() {
if (debugTexture == null) {
Pixmap pixmap = new Pixmap(texture.getRegionWidth(), texture.getRegionHeight(), Pixmap.Format.RGBA8888);
pixmap.setColor(Color.RED);
pixmap.drawRectangle(0, 0, (int) getWidth(), (int) getHeight());
debugTexture = new Texture(pixmap);
pixmap.dispose();
}
return debugTexture;
}
public Rectangle getBoundingRect() {
return boundingRect;
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
//batch.draw(getDebugTexture(),getX(),getY());
}
}

View File

@@ -0,0 +1,62 @@
package forge.adventure.stage;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.utils.SnapshotArray;
import java.util.Arrays;
import java.util.Comparator;
/**
* Sprite group to order actors based on the Y position on the map, the render sprites further up first.
*/
public class SpriteGroup extends Group {
/**
* Draws all children. {@link #applyTransform(Batch, Matrix4)} should be called before and {@link #resetTransform(Batch)}
* after this method if {@link #setTransform(boolean) transform} is true. If {@link #setTransform(boolean) transform} is false
* these methods don't need to be called, children positions are temporarily offset by the group position when drawn. This
* method avoids drawing children completely outside the {@link #setCullingArea(Rectangle) culling area}, if set.
*/
@Override
protected void drawChildren(Batch batch, float parentAlpha) {
Actor[] actors = getChildren().toArray();
Arrays.sort(actors, Comparator.comparingInt(o -> (int) -o.getY()));
for(int i=0;i<actors.length;i++)
{
if(i!=actors[i].getZIndex())
actors[i].setZIndex(i);
}
super.drawChildren(batch, parentAlpha);
}
@Override
public void addActor(Actor actor) {
for (Actor child : getChildren()) {
if (child.getY() < actor.getY()) {
super.addActorBefore(child, actor);
return;
}
}
super.addActor(actor);
}
public void UpdateActorZ(Actor actor) {
SnapshotArray<Actor> children = getChildren();
for (int i = 0; i < children.size; i++) {
if (children.get(i).getY() < actor.getY()) {
actor.setZIndex(i);
return;
}
}
actor.setZIndex(children.size);
}
}

View File

@@ -0,0 +1,157 @@
package forge.adventure.stage;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.scenes.scene2d.Actor;
import forge.adventure.world.WorldSave;
import java.awt.*;
import java.util.ArrayList;
/**
* Background for the over world, will get biome information and create chunks based on the terrain.
*/
public class WorldBackground extends Actor {
int chunkSize;
int tileSize;
int playerX;
int playerY;
Texture[][] chunks;
Texture loadingTexture;
ArrayList<Actor>[][] chunksSprites;
ArrayList<Actor>[][] chunksSpritesBackground;
int currentChunkX;
int currentChunkY;
GameStage stage;
public WorldBackground(GameStage gameStage) {
stage = gameStage;
}
public void draw(Batch batch, float parentAlpha) {
if (chunks == null) {
initialize();
}
Point pos = translateFromWorldToChunk(playerX, playerY);
if (currentChunkX != pos.x || currentChunkY != pos.y) {
int xDiff = currentChunkX - pos.x;
int yDiff = currentChunkY - pos.y;
ArrayList<Point> points = new ArrayList<Point>();
for (int x = -1; x < 2; x++) {
for (int y = -1; y < 2; y++) {
points.add(new Point(pos.x + x, pos.y + y));
}
}
for (int x = -1; x < 2; x++) {
for (int y = -1; y < 2; y++) {
Point point = new Point(currentChunkX + x, currentChunkY + y);
if (points.contains(point))// old Point is part of new points
{
points.remove(point);
} else {
if (point.y < 0 || point.x < 0 || point.y >= chunks[0].length || point.x >= chunks.length)
continue;
unLoadChunk(point.x, point.y);
}
}
}
for (Point point : points) {
if (point.y < 0 || point.x < 0 || point.y >= chunks[0].length || point.x >= chunks.length)
continue;
loadChunk(point.x, point.y);
}
currentChunkX = pos.x;
currentChunkY = pos.y;
}
batch.disableBlending();
for (int x = -1; x < 2; x++) {
for (int y = -1; y < 2; y++) {
if (pos.y + y < 0 || pos.x + x < 0 || pos.y >= chunks[0].length || pos.x >= chunks.length)
continue;
batch.draw(getChunkTexture(pos.x + x, pos.y + y), transChunkToWorld(pos.x + x), transChunkToWorld(pos.y + y));
}
}
batch.enableBlending();
}
private void loadChunk(int x, int y) {
if (chunksSprites[x][y] == null)
chunksSprites[x][y] = MapSprite.GetMapSprites(x, y);
for (Actor sprite : chunksSprites[x][y]) {
stage.GetSpriteGroup().addActor(sprite);
}
if (chunksSpritesBackground[x][y] == null)
chunksSpritesBackground[x][y] = MapSprite.GetMapSpritesBackground(x, y);
for (Actor sprite : chunksSpritesBackground[x][y]) {
stage.GetBackgroundSprites().addActor(sprite);
}
}
private void unLoadChunk(int x, int y) {
ArrayList<Actor> sprites = chunksSprites[x][y];
if (sprites != null) {
for (Actor sprite : sprites) {
stage.GetSpriteGroup().removeActor(sprite);
}
}
sprites = chunksSpritesBackground[x][y];
if (sprites != null) {
for (Actor sprite : sprites) {
stage.GetSpriteGroup().removeActor(sprite);
}
}
}
public Texture getChunkTexture(int x, int y) {
Texture tex = chunks[x][y];
if (tex == null) {
Texture newChunk = new Texture(chunkSize * tileSize, chunkSize * tileSize, Pixmap.Format.RGB888);
for (int cx = 0; cx < chunkSize; cx++) {
for (int cy = 0; cy < chunkSize; cy++) {
newChunk.draw(WorldSave.getCurrentSave().getWorld().getBiomeSprite(cx + chunkSize * x, cy + chunkSize * y), cx * tileSize, (chunkSize * tileSize) - (cy + 1) * tileSize);
}
}
chunks[x][y] = newChunk;
}
return chunks[x][y];
}
public void initialize() {
tileSize = WorldSave.getCurrentSave().getWorld().getTileSize();
chunkSize = WorldSave.getCurrentSave().getWorld().getChunkSize();
chunks = new Texture[WorldSave.getCurrentSave().getWorld().getWidthInTiles()][WorldSave.getCurrentSave().getWorld().getHeightInTiles()];
ArrayList[][] createChunks = new ArrayList[WorldSave.getCurrentSave().getWorld().getWidthInTiles()][WorldSave.getCurrentSave().getWorld().getHeightInTiles()];
chunksSprites = createChunks;
ArrayList[][] createSprites = new ArrayList[WorldSave.getCurrentSave().getWorld().getWidthInTiles()][WorldSave.getCurrentSave().getWorld().getHeightInTiles()];
chunksSpritesBackground = createSprites;
Pixmap loadPix = new Pixmap(chunkSize * tileSize, chunkSize * tileSize, Pixmap.Format.RGB565);
loadPix.setColor(0.5f, 0.5f, 0.5f, 1);
loadPix.fill();
loadingTexture = new Texture(loadPix);
}
int transChunkToWorld(int xy) {
return xy * tileSize * chunkSize;
}
Point translateFromWorldToChunk(float x, float y) {
float worldWidthTiles = x / tileSize;
float worldHeightTiles = y / tileSize;
return new Point((int) worldWidthTiles / chunkSize, (int) worldHeightTiles / chunkSize);
}
public void setPlayerPos(float x, float y) {
playerX = (int) x;
playerY = (int) y;
}
}

View File

@@ -0,0 +1,235 @@
package forge.adventure.stage;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import forge.adventure.AdventureApplicationAdapter;
import forge.adventure.character.CharacterSprite;
import forge.adventure.character.EnemySprite;
import forge.adventure.data.BiomeData;
import forge.adventure.data.EnemyData;
import forge.adventure.scene.*;
import forge.adventure.util.Current;
import forge.adventure.world.World;
import forge.adventure.world.WorldSave;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
/**
* Stage for the over world. Will handle monster spawns
*/
public class WorldStage extends GameStage {
private static WorldStage instance=null;
protected EnemySprite currentMob;
protected Random rand = new Random();
WorldBackground background;
private float spawnDelay = 0;
private final float spawnInterval = 4;//todo config
private PointOfInterestMapSprite collidingPoint;
protected ArrayList<Pair<Float, EnemySprite>> enemies = new ArrayList<>();
private final Float dieTimer=20f;//todo config
private Float globalTimer=0f;
public WorldStage() {
super();
background = new WorldBackground(this);
addActor(background);
background.setZIndex(0);
}
public static WorldStage getInstance() {
return instance == null ? instance = new WorldStage() : instance;
}
@Override
protected void onActing(float delta) {
if (player.isMoving()) {
HandleMonsterSpawn(delta);
handlePointsOfInterestCollision();
globalTimer+=delta;
Iterator<Pair<Float, EnemySprite>> it = enemies.iterator();
while (it.hasNext()) {
Pair<Float, EnemySprite> pair= it.next();
if(globalTimer>=pair.getKey()+dieTimer)
{
foregroundSprites.removeActor(pair.getValue());
it.remove();
continue;
}
EnemySprite mob=pair.getValue();
mob.moveTo(player,delta);
if (player.collideWith(mob)) {
player.setAnimation(CharacterSprite.AnimationTypes.Attack);
mob.setAnimation(CharacterSprite.AnimationTypes.Attack);
startPause(1,()->{
((DuelScene) SceneType.DuelScene.instance).setEnemy(currentMob);
((DuelScene) SceneType.DuelScene.instance).setPlayer(player);
AdventureApplicationAdapter.instance.switchScene(SceneType.DuelScene.instance);
});
currentMob = mob;
break;
}
}
} else {
for (Pair<Float, EnemySprite> pair : enemies) {
pair.getValue().setAnimation(CharacterSprite.AnimationTypes.Idle);
}
}
}
private void removeEnemy(EnemySprite currentMob) {
foregroundSprites.removeActor(currentMob);
Iterator<Pair<Float, EnemySprite>> it = enemies.iterator();
while (it.hasNext()) {
Pair<Float, EnemySprite> pair = it.next();
if (pair.getValue()==currentMob) {
it.remove();
return;
}
}
}
@Override
public void setWinner(boolean playerIsWinner) {
if (playerIsWinner) {
player.setAnimation(CharacterSprite.AnimationTypes.Attack);
currentMob.setAnimation(CharacterSprite.AnimationTypes.Death);
startPause(1,()->
{
((RewardScene)SceneType.RewardScene.instance).loadRewards(currentMob.getRewards(), RewardScene.Type.Loot, null);
removeEnemy(currentMob);
currentMob = null;
AdventureApplicationAdapter.instance.switchScene(SceneType.RewardScene.instance);
} );
} else {
player.setAnimation(CharacterSprite.AnimationTypes.Hit);
currentMob.setAnimation(CharacterSprite.AnimationTypes.Attack);
startPause(1,()->
{
Current.player().defeated();
removeEnemy(currentMob);
currentMob = null;
} );
}
}
private void handlePointsOfInterestCollision() {
for (Actor actor : foregroundSprites.getChildren()) {
if (actor.getClass() == PointOfInterestMapSprite.class) {
PointOfInterestMapSprite point = (PointOfInterestMapSprite) actor;
if (player.collideWith(point.getBoundingRect())) {
if (point == collidingPoint) {
continue;
}
((TileMapScene) SceneType.TileMapScene.instance).load(point.getPointOfInterest());
AdventureApplicationAdapter.instance.switchScene(SceneType.TileMapScene.instance);
} else {
if (point == collidingPoint) {
collidingPoint = null;
}
}
}
}
}
@Override
public boolean isColliding(Rectangle boundingRect)
{
World world = WorldSave.getCurrentSave().getWorld();
int currentBiome = World.highestBiome(world.getBiome((int) boundingRect.getX() / world.getTileSize(), (int) boundingRect.getY() / world.getTileSize()));
if(currentBiome==0)
return true;
currentBiome = World.highestBiome(world.getBiome((int) (boundingRect.getX()+boundingRect.getWidth()) / world.getTileSize(), (int) boundingRect.getY() / world.getTileSize()));
if(currentBiome==0)
return true;
currentBiome = World.highestBiome(world.getBiome((int) (boundingRect.getX()+boundingRect.getWidth())/ world.getTileSize(), (int) (boundingRect.getY()+boundingRect.getHeight()) / world.getTileSize()));
if(currentBiome==0)
return true;
currentBiome = World.highestBiome(world.getBiome((int) boundingRect.getX() / world.getTileSize(), (int) (boundingRect.getY()+boundingRect.getHeight()) / world.getTileSize()));
return (currentBiome==0);
}
private void HandleMonsterSpawn(float delta) {
World world = WorldSave.getCurrentSave().getWorld();
int currentBiome = World.highestBiome(world.getBiome((int) player.getX() / world.getTileSize(), (int) player.getY() / world.getTileSize()));
List<BiomeData> biomeData = WorldSave.getCurrentSave().getWorld().getData().GetBiomes();
if (biomeData.size() <= currentBiome)
{
player.setMoveModifier(1.5f);
return;
}
player.setMoveModifier(1.0f);
BiomeData data = biomeData.get(currentBiome);
if (data == null)
return;
ArrayList<EnemyData> list = data.getEnemyList();
if (list == null)
return;
spawnDelay -= delta;
if(spawnDelay>=0)
return;
spawnDelay=spawnInterval+(rand.nextFloat()*4);
EnemyData enemyData = data.getEnemy( 1);
if (enemyData == null) {
return;
}
EnemySprite sprite = new EnemySprite(enemyData);
float unit = Scene.GetIntendedHeight() / 6f;
Vector2 spawnPos = new Vector2(1, 1);
spawnPos.setLength(unit + (unit * 3) * rand.nextFloat());
spawnPos.setAngleDeg(360 * rand.nextFloat());
sprite.setX(player.getX() + spawnPos.x);
sprite.setY(player.getY() + spawnPos.y);
enemies.add(Pair.of(globalTimer,sprite));
foregroundSprites.addActor(sprite);
}
@Override
public void draw() {
getBatch().begin();
background.setPlayerPos(player.getX(), player.getY());
getBatch().end();
//spriteGroup.setCullingArea(new Rectangle(player.getX()-getViewport().getWorldHeight()/2,player.getY()-getViewport().getWorldHeight()/2,getViewport().getWorldHeight(),getViewport().getWorldHeight()));
super.draw();
}
@Override
public void enter() {
GetPlayer().LoadPos();
GetPlayer().setMovementDirection(Vector2.Zero);
for (Actor actor : foregroundSprites.getChildren()) {
if (actor.getClass() == PointOfInterestMapSprite.class) {
PointOfInterestMapSprite point = (PointOfInterestMapSprite) actor;
if (player.collideWith(point.getBoundingRect())) {
collidingPoint = point;
}
}
}
setBounds(WorldSave.getCurrentSave().getWorld().getWidthInPixels(), WorldSave.getCurrentSave().getWorld().getHeightInPixels());
}
@Override
public void leave() {
GetPlayer().storePos();
}
}

View File

@@ -0,0 +1,500 @@
package forge.adventure.util;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Json;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.adventure.data.GeneratedDeckData;
import forge.adventure.data.GeneratedDeckTemplateData;
import forge.adventure.data.RewardData;
import forge.adventure.world.WorldSave;
import forge.card.CardRarity;
import forge.card.CardType;
import forge.card.MagicColor;
import forge.card.mana.ManaCostShard;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.deck.io.DeckSerializer;
import forge.item.PaperCard;
import forge.model.FModel;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
/**
* Utility class to deck generation and card filtering
*/
public class CardUtil {
public static final class CardPredicate implements Predicate<PaperCard> {
enum ColorType
{
Any,
Colorless,
MultiColor,
MonoColor
}
private final List<CardRarity> rarities=new ArrayList<>();
private final List<String> editions=new ArrayList<>();
private final List<String> subType=new ArrayList<>();
private final List<String> keyWords=new ArrayList<>();
private final List<CardType.CoreType> type=new ArrayList<>();
private final List<CardType.Supertype> superType=new ArrayList<>();
private final List<Integer> manaCosts =new ArrayList<>();
private final Pattern text;
private final boolean matchAllSubTypes;
private int colors;
private final ColorType colorType;
private final boolean shouldBeEqual;
@Override
public boolean apply(final PaperCard card) {
if(!this.rarities.isEmpty()&&!this.rarities.contains(card.getRarity()))
return !this.shouldBeEqual;
if(!this.editions.isEmpty()&&!this.editions.contains(card.getEdition()))
return !this.shouldBeEqual;
if(!this.manaCosts.isEmpty()&&!this.manaCosts.contains(card.getRules().getManaCost().getCMC()))
return !this.shouldBeEqual;
if(this.text!=null&& !this.text.matcher(card.getRules().getOracleText()).find())
return !this.shouldBeEqual;
if(this.colors!= MagicColor.ALL_COLORS)
{
if(!card.getRules().getColor().hasNoColorsExcept(this.colors)||card.getRules().getColor().isColorless())
return !this.shouldBeEqual;
}
if(colorType!=ColorType.Any)
{
switch (colorType)
{
case Colorless:
if(!card.getRules().getColor().isColorless())
return !this.shouldBeEqual;
break;
case MonoColor:
if(!card.getRules().getColor().isMonoColor())
return !this.shouldBeEqual;
break;
case MultiColor:
if(!card.getRules().getColor().isMulticolor())
return !this.shouldBeEqual;
break;
}
}
if(!this.type.isEmpty())
{
boolean found=false;
for(CardType.CoreType type:card.getRules().getType().getCoreTypes())
{
if(this.type.contains(type))
{
found=true;
break;
}
}
if(!found)
return !this.shouldBeEqual;
}
if(!this.superType.isEmpty())
{
boolean found=false;
for(CardType.Supertype type:card.getRules().getType().getSupertypes())
{
if(this.superType.contains(type))
{
found=true;
break;
}
}
if(!found)
return !this.shouldBeEqual;
}
if(this.matchAllSubTypes)
{
if(!this.subType.isEmpty())
{
if(this.subType.size()!= Iterables.size(card.getRules().getType().getSubtypes()))
return !this.shouldBeEqual;
for(String subtype:card.getRules().getType().getSubtypes())
{
if(!this.subType.contains(subtype))
{
return !this.shouldBeEqual;
}
}
}
}
else
{
if(!this.subType.isEmpty())
{
boolean found=false;
for(String subtype:card.getRules().getType().getSubtypes())
{
if(this.subType.contains(subtype))
{
found=true;
break;
}
}
if(!found)
return !this.shouldBeEqual;
}
}
if(!this.keyWords.isEmpty())
{
boolean found=false;
for(String keyWord:this.keyWords)
{
if(card.getRules().hasKeyword(keyWord))
{
found=true;
break;
}
}
if(!found)
return !this.shouldBeEqual;
}
return this.shouldBeEqual;
}
public CardPredicate(final RewardData type, final boolean wantEqual) {
this.matchAllSubTypes=type.matchAllSubTypes;
this.shouldBeEqual = wantEqual;
for(int i=0;type.manaCosts!=null&&i<type.manaCosts.length;i++)
manaCosts.add(type.manaCosts[i]);
text = type.cardText==null||type.cardText.isEmpty()?null:Pattern.compile(type.cardText, Pattern.CASE_INSENSITIVE);
if(type.colors==null||type.colors.length==0)
{
this.colors=MagicColor.ALL_COLORS;
}
else
{
this.colors=0;
for(String color:type.colors)
{
colors|=MagicColor.fromName(color.toLowerCase());
}
}
if(type.keyWords!=null&&type.keyWords.length!=0)
{
keyWords.addAll(Arrays.asList(type.keyWords));
}
if(type.rarity!=null&&type.rarity.length!=0)
{
for(String rarity:type.rarity)
{
rarities.add(CardRarity.smartValueOf(rarity));
}
}
if(type.subTypes!=null&&type.subTypes.length!=0)
{
subType.addAll(Arrays.asList(type.subTypes));
}
if(type.editions!=null&&type.editions.length!=0)
{
editions.addAll(Arrays.asList(type.editions));
}
if(type.superTypes!=null&&type.superTypes.length!=0)
{
for(String string:type.superTypes)
superType.add(CardType.Supertype.getEnum(string));
}
if(type.cardTypes!=null&&type.cardTypes.length!=0)
{
for(String string:type.cardTypes)
this.type.add(CardType.CoreType.getEnum(string));
}
if(type.colorType!=null&&!type.colorType.isEmpty())
{
this.colorType=ColorType.valueOf(type.colorType);
}
else
{
this.colorType=ColorType.Any;
}
}
}
public static List<PaperCard> generateCards(Iterable<PaperCard> cards,final RewardData data, final int count)
{
final List<PaperCard> result = new ArrayList<>();
for (int i=0;i<count;i++) {
CardPredicate pre=new CardPredicate(data, true);
PaperCard card = null;
int lowest = Integer.MAX_VALUE;
for (final PaperCard item : cards)
{
if(!pre.apply(item))
continue;
int next = WorldSave.getCurrentSave().getWorld().getRandom().nextInt();
if(next < lowest) {
lowest = next;
card = item;
}
}
if (card != null )
result.add(card);
}
return result;
}
public static int getCardPrice(PaperCard card)
{
switch (card.getRarity())
{
case BasicLand:
return 20;
case Common:
return 50;
case Uncommon:
return 150;
case Rare:
return 300;
case MythicRare:
return 500;
default:
return 90000;
}
}
public static Deck generateDeck(GeneratedDeckData data)
{
Deck deck= new Deck(data.name);
if(data.template==null)
{
deck.getOrCreate(DeckSection.Main).addAllFlat(RewardData.generateAllCards(Arrays.asList(data.mainDeck), true));
if(data.sideBoard!=null)
deck.getOrCreate(DeckSection.Sideboard).addAllFlat(RewardData.generateAllCards(Arrays.asList(data.sideBoard), true));
return deck;
}
float count=data.template.count;
float lands=count*0.4f;
float spells=count-lands;
List<RewardData> dataArray= generateRewards(data.template,spells*0.5f,new int[]{1,2});
dataArray.addAll(generateRewards(data.template,spells*0.3f,new int[]{3,4,5}));
dataArray.addAll(generateRewards(data.template,spells*0.2f,new int[]{6,7,8}));
List<PaperCard> nonLand=RewardData.generateAllCards(dataArray, true);
nonLand.addAll(fillWithLands(nonLand,data.template));
deck.getOrCreate(DeckSection.Main).addAllFlat(nonLand);
return deck;
}
private static List<PaperCard> fillWithLands(List<PaperCard> nonLands, GeneratedDeckTemplateData template) {
int red=0;
int blue=0;
int green=0;
int white=0;
int black=0;
int colorLess=0;
int cardCount=nonLands.size();
List<PaperCard> cards=new ArrayList<>();
for(PaperCard nonLand:nonLands)
{
red+=nonLand.getRules().getManaCost().getShardCount(ManaCostShard.RED);
green+=nonLand.getRules().getManaCost().getShardCount(ManaCostShard.GREEN);
white+=nonLand.getRules().getManaCost().getShardCount(ManaCostShard.WHITE);
blue+=nonLand.getRules().getManaCost().getShardCount(ManaCostShard.BLUE);
black+=nonLand.getRules().getManaCost().getShardCount(ManaCostShard.BLACK);
colorLess+=nonLand.getRules().getManaCost().getShardCount(ManaCostShard.GENERIC);
}
float sum= red+ blue+ green+ white+ black;
int neededLands=template.count-cardCount;
int neededDualLands= Math.round (neededLands*template.rares);
int neededBase=neededLands-neededDualLands;
if(sum==0.)
{
cards.addAll(generateLands("Wastes",neededLands));
}
else
{
int mount=Math.round(neededBase*(red/sum));
int island=Math.round(neededBase*(blue/sum));
int forest=Math.round(neededBase*(green/sum));
int plains=Math.round(neededBase*(white/sum));
int swamp=Math.round(neededBase*(black/sum));
cards.addAll(generateLands("Plains",plains));
cards.addAll(generateLands("Island",island));
cards.addAll(generateLands("Forest",forest));
cards.addAll(generateLands("Mountain",mount));
cards.addAll(generateLands("Swamp",swamp));
List<String> landTypes=new ArrayList<>();
if(mount>0)
landTypes.add("Mountain");
if(island>0)
landTypes.add("Island");
if(plains>0)
landTypes.add("Plains");
if(swamp>0)
landTypes.add("Swamp");
if(forest>0)
landTypes.add("Forest");
cards.addAll(generateDualLands(landTypes,neededDualLands));
}
return cards;
}
private static Collection<PaperCard> generateDualLands(List<String> landName, int count) {
ArrayList<RewardData> rewards=new ArrayList<>();
RewardData base= new RewardData();
rewards.add(base);
base.cardTypes=new String[]{"Land"};
base.count=count;
base.matchAllSubTypes=true;
if(landName.size()==1)
{
base.subTypes=new String[]{landName.get(0)};
}
else if(landName.size()==2)
{
base.subTypes=new String[]{landName.get(0),landName.get(1)};
}
else if(landName.size()==3)
{
RewardData sub1= new RewardData(base);
RewardData sub2= new RewardData(base);
sub1.count/=3;
sub2.count/=3;
base.count-=sub1.count;
base.count-=sub2.count;
base.subTypes=new String[]{landName.get(0),landName.get(1)};
sub1.subTypes=new String[]{landName.get(1),landName.get(2)};
sub2.subTypes=new String[]{landName.get(0),landName.get(2)};
rewards.addAll(Arrays.asList(sub1,sub2));
}
else if(landName.size()==4)
{
RewardData sub1= new RewardData(base);
RewardData sub2= new RewardData(base);
RewardData sub3= new RewardData(base);
RewardData sub4= new RewardData(base);
sub1.count/=5;
sub2.count/=5;
sub3.count/=5;
sub4.count/=5;
base.count-=sub1.count;
base.count-=sub2.count;
base.count-=sub3.count;
base.count-=sub4.count;
base.subTypes = new String[]{landName.get(0),landName.get(1)};
sub1.subTypes = new String[]{landName.get(0),landName.get(2)};
sub2.subTypes = new String[]{landName.get(0),landName.get(3)};
sub3.subTypes = new String[]{landName.get(1),landName.get(2)};
sub4.subTypes = new String[]{landName.get(1),landName.get(3)};
rewards.addAll(Arrays.asList(sub1,sub2,sub3,sub4));
}
else if(landName.size()==5)
{
RewardData sub1= new RewardData(base);
RewardData sub2= new RewardData(base);
RewardData sub3= new RewardData(base);
RewardData sub4= new RewardData(base);
RewardData sub5= new RewardData(base);
RewardData sub6= new RewardData(base);
RewardData sub7= new RewardData(base);
RewardData sub8= new RewardData(base);
RewardData sub9= new RewardData(base);
sub1.count/=10;
sub2.count/=10;
sub3.count/=10;
sub4.count/=10;
sub5.count/=10;
sub6.count/=10;
sub7.count/=10;
sub8.count/=10;
sub9.count/=10;
base.count-=sub1.count;
base.count-=sub2.count;
base.count-=sub3.count;
base.count-=sub4.count;
base.count-=sub5.count;
base.count-=sub6.count;
base.count-=sub7.count;
base.count-=sub8.count;
base.count-=sub9.count;
base.subTypes=new String[]{landName.get(0),landName.get(1)};
sub1.subTypes=new String[]{landName.get(0),landName.get(2)};
sub2.subTypes=new String[]{landName.get(0),landName.get(3)};
sub3.subTypes=new String[]{landName.get(0),landName.get(4)};
sub4.subTypes=new String[]{landName.get(1),landName.get(2)};
sub5.subTypes=new String[]{landName.get(1),landName.get(3)};
sub6.subTypes=new String[]{landName.get(1),landName.get(4)};
sub7.subTypes=new String[]{landName.get(2),landName.get(3)};
sub8.subTypes=new String[]{landName.get(2),landName.get(4)};
sub9.subTypes=new String[]{landName.get(3),landName.get(4)};
rewards.addAll(Arrays.asList(sub1,sub2,sub3,sub4,sub5,sub6,sub7,sub8,sub9));
}
Collection<PaperCard> ret = new ArrayList<>(RewardData.generateAllCards(rewards, true));
return ret;
}
private static Collection<PaperCard> generateLands(String landName,int count) {
Collection<PaperCard> ret=new ArrayList<>();
for(int i=0;i<count;i++)
ret.add(FModel.getMagicDb().getCommonCards().getCard(landName));
return ret;
}
private static List<RewardData> generateRewards(GeneratedDeckTemplateData template, float count, int[] manaCosts) {
ArrayList<RewardData> ret=new ArrayList<>();
ret.addAll(templateGenerate(template,count-(count*template.rares),manaCosts,new String[]{"Uncommon","Common"}));
ret.addAll(templateGenerate(template,count*template.rares,manaCosts,new String[]{"Rare","Mythic Rare"}));
return ret;
}
private static ArrayList<RewardData> templateGenerate(GeneratedDeckTemplateData template, float count, int[] manaCosts, String[] strings) {
ArrayList<RewardData> ret=new ArrayList<>();
RewardData base= new RewardData();
base.manaCosts=manaCosts;
base.rarity=strings;
base.colors=template.colors;
if(template.tribe!=null&&!template.tribe.isEmpty())
{
RewardData caresAbout= new RewardData(base);
caresAbout.cardText="\\b"+template.tribe+"\\b";
caresAbout.count= Math.round(count*template.tribeSynergyCards);
ret.add(caresAbout);
base.subTypes=new String[]{template.tribe};
base.count= Math.round(count*(1-template.tribeSynergyCards));
}
else
{
base.count= Math.round(count);
}
ret.add(base);
return ret;
}
public static Deck getDeck(String path)
{
if(path.endsWith(".dck"))
return DeckSerializer.fromFile(new File(Config.instance().getFilePath(path)));
Json json = new Json();
FileHandle handle = Config.instance().getFile(path);
if (handle.exists())
return generateDeck(json.fromJson(GeneratedDeckData.class, handle));
return null;
}
}

View File

@@ -0,0 +1,139 @@
package forge.adventure.util;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonWriter;
import forge.adventure.data.ConfigData;
import forge.adventure.data.SettingData;
import forge.deck.Deck;
import forge.localinstance.properties.ForgeConstants;
import forge.localinstance.properties.ForgePreferences;
import forge.localinstance.properties.ForgeProfileProperties;
import forge.model.FModel;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
/**
* Main resource class to access files from the selected adventure
*/
public class Config {
private static Config currentConfig;
private final String prefix;
private final HashMap<String, FileHandle> Cache = new HashMap<String, FileHandle>();
private final HashMap<String, TextureAtlas> atlasCache = new HashMap<>();
private final ConfigData configData;
private final String[] adventures;
private SettingData settingsData;
private String Lang = "en-us";
private final String plane;
static public Config instance()
{
if(currentConfig==null)
currentConfig=new Config();
return currentConfig;
}
private Config() {
String path= Files.exists(Paths.get("./res"))?"./":"../forge-gui/";
adventures = new File(path + "/res/adventure").list();
try
{
settingsData = new Json().fromJson(SettingData.class, new FileHandle(ForgeConstants.USER_DIR + "/adventure/settings.json"));
}
catch (Exception e)
{
settingsData=new SettingData();
}
if(settingsData.plane==null||settingsData.plane.isEmpty())
{
if(adventures!=null&&adventures.length>=1)
settingsData.plane=adventures[0];
}
if(settingsData.width==0||settingsData.height==0)
{
settingsData.width=1280;
settingsData.height=720;
}
this.plane = settingsData.plane;
currentConfig = this;
prefix = path + "/res/adventure/" + plane + "/";
if (FModel.getPreferences() != null)
Lang = FModel.getPreferences().getPref(ForgePreferences.FPref.UI_LANGUAGE);
configData = new Json().fromJson(ConfigData.class, new FileHandle(prefix + "config.json"));
}
public ConfigData getConfigData() {
return configData;
}
public String getPrefix() {
return prefix;
}
public String getFilePath(String path) {
return prefix + path;
}
public FileHandle getFile(String path) {
String fullPath = prefix + path;
if (!Cache.containsKey(fullPath)) {
String fileName = fullPath.replaceFirst("[.][^.]+$", "");
String ext = fullPath.substring(fullPath.lastIndexOf('.'));
String langFile = fileName + "-" + Lang + ext;
if (Files.exists(Paths.get(langFile))) {
Cache.put(fullPath, new FileHandle(langFile));
} else {
Cache.put(fullPath, new FileHandle(fullPath));
}
}
return Cache.get(fullPath);
}
public String getPlane() {
return plane;
}
public Deck[] starterDecks() {
Deck[] deck = new Deck[configData.starterDecks.length];
for (int i = 0; i < configData.starterDecks.length; i++) {
deck[i] = CardUtil.getDeck(configData.starterDecks[i]);
}
return deck;
}
public TextureAtlas getAtlas(String spriteAtlas) {
if (!atlasCache.containsKey(spriteAtlas)) {
atlasCache.put(spriteAtlas, new TextureAtlas(getFile(spriteAtlas)));
}
return atlasCache.get(spriteAtlas);
}
public SettingData getSettingData()
{
return settingsData;
}
public String[] getAllAdventures()
{
return adventures;
}
public void saveSettings() {
Json json = new Json(JsonWriter.OutputType.json);
FileHandle handle = new FileHandle(ForgeProfileProperties.getUserDir() + "/adventure/settings.json");
handle.writeString(json.prettyPrint(json.toJson(settingsData, SettingData.class)),false);
}
}

View File

@@ -0,0 +1,129 @@
package forge.adventure.util;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import java.util.function.Function;
/**
* Class to create ui elements in the correct style
*/
public class Controls {
private static Skin SelectedSkin = null;
static public TextButton newTextButton(String text) {
return new TextButton(text, GetSkin());
}
static public SelectBox newComboBox(String[] text, String item, Function<Object, Void> func) {
SelectBox ret = new SelectBox<String>(GetSkin());
ret.setItems(text);
ret.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
try {
func.apply(((SelectBox) actor).getSelected());
} catch (Exception e) {
e.printStackTrace();
}
}
});
func.apply(item);
ret.setSelected(item);
return ret;
}
static public TextField newTextField(String text) {
return new TextField(text, GetSkin());
}
static public TextField newTextField(String text, Function<String, Void> func) {
TextField ret = new TextField(text, GetSkin());
ret.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
try {
func.apply(((TextField) actor).getText());
} catch (Exception e) {
e.printStackTrace();
}
}
});
return ret;
}
static public TextButton newTextButton(String text, Runnable func) {
TextButton ret = newTextButton(text);
ret.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
try {
func.run();
} catch (Exception e) {
e.printStackTrace();
}
}
});
return ret;
}
static public Slider newSlider(float min, float max, float step, boolean vertical) {
Slider ret = new Slider(min, max, step, vertical, GetSkin());
return ret;
}
static public CheckBox newCheckBox(String text) {
CheckBox ret = new CheckBox(text, GetSkin());
return ret;
}
static public BitmapFont bigFont()
{
return SelectedSkin.getFont("big");
}
static public BitmapFont font()
{
return SelectedSkin.getFont("default");
}
static public Skin GetSkin() {
if (SelectedSkin == null) {
SelectedSkin = new Skin();
FileHandle skinFile = Config.instance().getFile(Paths.SKIN);
FileHandle atlasFile = skinFile.sibling(skinFile.nameWithoutExtension() + ".atlas");
TextureAtlas atlas = new TextureAtlas(atlasFile);
SelectedSkin.addRegions(atlas);
SelectedSkin.load(skinFile);
}
return SelectedSkin;
}
public static Label newLabel(String name) {
Label ret = new Label(name, GetSkin());
return ret;
}
public static Dialog newDialog(String title) {
Dialog ret = new Dialog(title, GetSkin());
return ret;
}
}

View File

@@ -0,0 +1,22 @@
package forge.adventure.util;
import forge.adventure.world.AdventurePlayer;
import forge.adventure.world.WorldSave;
import forge.deck.Deck;
/**
* Shortcut class to handle global access, may need some redesign
*/
public class Current {
public static AdventurePlayer player()
{
return WorldSave.getCurrentSave().getPlayer();
}
static Deck deck;
public static Deck latestDeck() {
return deck;
}
public static void setLatestDeck(Deck generateDeck) {
deck=generateDeck;
}
}

View File

@@ -0,0 +1,48 @@
package forge.adventure.util;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.TextureData;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
/*
Class to draw directly on a pixmap
*/
public abstract class DrawOnPixmap {
public static void draw(Pixmap on, TextureRegion from)
{
draw(on,0,0,from);
}
public static void draw(Pixmap on,int x,int y, TextureRegion from)
{
TextureData textureData = from.getTexture().getTextureData();
if (!textureData.isPrepared()) {
textureData.prepare();
}
on.drawPixmap( textureData.consumePixmap(), x, y, from.getRegionX(), from.getRegionY(), from.getRegionWidth(), from.getRegionHeight() );
}
public static void drawText(Pixmap drawingMap, String text, int x, int y, float width) {
BitmapFont font=Controls.bigFont();
BitmapFont.BitmapFontData data=font.getData();
Pixmap source=new Pixmap(Gdx.files.internal(data.imagePaths[0]));
float totalLength=data.getGlyph('0').width*text.length();
float xOffset=(width-totalLength)/2;
xOffset+=x;
for(char c:text.toCharArray())
{
drawingMap.drawPixmap(source, (int)xOffset, y,
data.getGlyph(c).srcX, data.getGlyph(c).srcY, data.getGlyph(c).width, data.getGlyph(c).height);
xOffset+=data.getGlyph(c).width+1;
}
source.dispose();
}
}

View File

@@ -0,0 +1,16 @@
package forge.adventure.util;
/**
* Defines for the hard coded paths
*/
public class Paths {
public static final String ENEMIES = "world/enemies.json";
public static final String SHOPS = "world/shops.json";
public static final String WORLD = "world/world.json";
public static final String HEROES = "world/heroes.json";
public static final String POINTS_OF_INTEREST = "world/points_of_interest.json";
public static final String SKIN = "skin/ui_skin.json";
}

View File

@@ -0,0 +1,53 @@
package forge.adventure.util;
import forge.item.PaperCard;
/**
* Reward class that may contain gold,cards or items
*/
public class Reward {
public PaperCard getCard() {
return card;
}
public enum Type {
Card,
Gold,
Item,
Life
}
Type type;
PaperCard card;
private final int count;
public int getCount() {
return count;
}
public Type getType() {
return type;
}
public Reward(int count) {
type=Type.Gold;
this.count =count;
}
public Reward(PaperCard card)
{
type= Type.Card;
this.card=card;
count = 0;
}
public Reward(Type type, int count) {
this.type=type;
this.count =count;
}
}

View File

@@ -0,0 +1,306 @@
package forge.adventure.util;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Tooltip;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Disposable;
import forge.adventure.scene.RewardScene;
import forge.adventure.scene.Scene;
import forge.assets.FSkin;
import forge.assets.ImageCache;
import forge.gui.GuiBase;
import forge.util.ImageFetcher;
/**
* Render the rewards as a card on the reward scene.
*
*/
public class RewardActor extends Actor implements Disposable, ImageFetcher.Callback {
Tooltip<Image> tooltip;
Reward reward;
static TextureRegion backTexture;
Texture image;
boolean needsToBeDisposed;
float flipProcess=0;
boolean clicked=false;
boolean flipOnClick;
private boolean hover;
static final ImageFetcher fetcher = GuiBase.getInterface().getImageFetcher();
Image toolTipImage;
@Override
public void dispose() {
if(needsToBeDisposed)
image.dispose();
}
public Reward getReward() {
return reward;
}
@Override
public void onImageFetched() {
if(ImageCache.imageKeyFileExists(reward.getCard().getImageKey(false)))
{
setCardImage(ImageCache.getImage(reward.getCard().getImageKey(false),false));
}
}
public enum Type
{
Shop,
Loot
}
public RewardActor(Reward reward,boolean flippable)
{
this.flipOnClick=flippable;
this.reward=reward;
if(backTexture==null)
{
backTexture= FSkin.getSleeves().get(0);
}
switch (reward.type)
{
case Card:
if(ImageCache.imageKeyFileExists(reward.getCard().getImageKey(false)))
{
setCardImage( ImageCache.getImage(reward.getCard().getImageKey(false),false));
}
else
{
if (!ImageCache.imageKeyFileExists(reward.getCard().getImageKey(false))) {
fetcher.fetchImage(reward.getCard().getImageKey(false), this);
}
}
break;
case Gold:
{
TextureAtlas atlas= Config.instance().getAtlas("sprites/items.atlas");
Sprite backSprite=atlas.createSprite("CardBack");
Pixmap drawingMap=new Pixmap((int)backSprite.getWidth(),(int)backSprite.getHeight(), Pixmap.Format.RGBA8888);
DrawOnPixmap.draw(drawingMap,backSprite);
Sprite gold=atlas.createSprite("Gold");
DrawOnPixmap.draw(drawingMap,(int)((backSprite.getWidth()/2f)-gold.getWidth()/2f),(int)((backSprite.getHeight()/4f)*1f),gold);
DrawOnPixmap.drawText(drawingMap,String.valueOf(reward.getCount()),0,(int)((backSprite.getHeight()/4f)*2f),backSprite.getWidth());
image=new Texture(drawingMap);
drawingMap.dispose();
needsToBeDisposed=true;
break;
}
case Life:
{
TextureAtlas atlas = Config.instance().getAtlas("sprites/items.atlas");
Sprite backSprite = atlas.createSprite("CardBack");
Pixmap drawingMap = new Pixmap((int) backSprite.getWidth(), (int) backSprite.getHeight(), Pixmap.Format.RGBA8888);
DrawOnPixmap.draw(drawingMap, backSprite);
Sprite gold = atlas.createSprite("Life");
DrawOnPixmap.draw(drawingMap, (int) ((backSprite.getWidth() / 2f) - gold.getWidth() / 2f), (int) ((backSprite.getHeight() / 4f) * 1f), gold);
DrawOnPixmap.drawText(drawingMap, String.valueOf(reward.getCount()), 0, (int) ((backSprite.getHeight() / 4f) * 2f), backSprite.getWidth());
image = new Texture(drawingMap);
drawingMap.dispose();
needsToBeDisposed = true;
break;
}
}
addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
if(flipOnClick)
flip();
}
@Override
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor){
hover=true;
}
@Override
public void exit(InputEvent event, float x, float y, int pointer, Actor fromActor){
hover=false;
}
});
}
private void setCardImage(Texture img) {
image=img;
image.setFilter(Texture.TextureFilter.Linear,Texture.TextureFilter.Linear);
TextureRegionDrawable drawable=new TextureRegionDrawable(new TextureRegion(image));
drawable.setMinSize((Scene.GetIntendedHeight()/ RewardScene.CARD_WIDTH_TO_HEIGHT)*0.95f,Scene.GetIntendedHeight()*0.95f);
toolTipImage=new Image(drawable);
tooltip=new Tooltip<Image>(toolTipImage);
tooltip.setInstant(true);
if(frontSideUp())
addListener(tooltip);
}
private boolean frontSideUp() {
return (flipProcess >= 0.5f) == flipOnClick;
}
public boolean isFlipped() {
return (clicked&&flipProcess>=1);
}
public void flip() {
if(clicked)
return;
clicked=true;
flipProcess=0;
}
@Override
public void act(float delta)
{
super.act(delta);
if(clicked)
{
if(flipProcess<1)
flipProcess+=delta;
else
flipProcess=1;
if(tooltip!=null&&frontSideUp()&&!getListeners().contains(tooltip,true))
addListener(tooltip);
// flipProcess=(float)Gdx.input.getX()/ (float)Gdx.graphics.getWidth();
}
}
@Override
public void draw (Batch batch, float parentAlpha) {
applyTransform(batch, computeTransform(batch.getTransformMatrix().cpy()));
oldProjectionTransform.set(batch.getProjectionMatrix());
applyProjectionMatrix(batch);
if(hover)
batch.setColor(0.5f,0.5f,0.5f,1);
if(!frontSideUp())
{
batch.draw(backTexture,-getWidth()/2,-getHeight()/2,getWidth(),getHeight());
}
else
{
drawFrontSide(batch);
}
batch.setColor(1,1,1,1);
resetTransform(batch);
batch.setProjectionMatrix(oldProjectionTransform);
}
private void drawFrontSide(Batch batch) {
float width;
float x;
if(flipOnClick)
{
width=-getWidth();
x=-getWidth()/2+getWidth();
}
else
{
width=getWidth();
x=-getWidth()/2;
}
if (image != null)
batch.draw(image,x,-getHeight()/2,width,getHeight());
else
batch.draw(ImageCache.defaultImage,x,-getHeight()/2,width,getHeight());
switch (reward.getType())
{
case Card:
break;
case Gold:
break;
case Item:
break;
}
}
private void applyProjectionMatrix(Batch batch) {
final Vector3 direction = new Vector3(0, 0, -1);
final Vector3 up = new Vector3(0, 1, 0);
//final Vector3 position = new Vector3( getX()+getWidth()/2 , getY()+getHeight()/2, 0);
final Vector3 position = new Vector3( Scene.GetIntendedWidth() /2f , Scene.GetIntendedHeight()/2f, 0);
float fov=67;
Matrix4 projection=new Matrix4();
Matrix4 view=new Matrix4();
float hy= Scene.GetIntendedHeight()/2f;
float a= (float) ((hy)/Math.sin(MathUtils.degreesToRadians*(fov/2f)));
float height= (float) Math.sqrt((a*a)-(hy*hy));
position.z=height*1f;
float far=height*2f;
float near=height*0.8f;
float aspect = (float)Scene.GetIntendedWidth() / (float)Scene.GetIntendedHeight();
projection.setToProjection(Math.abs(near), Math.abs(far), fov, aspect);
view.setToLookAt(position, position.cpy().add(direction), up);
Matrix4.mul(projection.val, view.val);
batch.setProjectionMatrix(projection);
}
private final Matrix4 computedTransform = new Matrix4();
private final Matrix4 oldTransform = new Matrix4();
private final Matrix4 oldProjectionTransform = new Matrix4();
protected void applyTransform (Batch batch, Matrix4 transform)
{
oldTransform.set(batch.getTransformMatrix());
batch.setTransformMatrix(transform);
}
/** Restores the batch transform to what it was before {@link #applyTransform(Batch, Matrix4)}. Note this causes the batch to
* be flushed. */
protected void resetTransform (Batch batch) {
batch.setTransformMatrix(oldTransform);
}
protected Matrix4 computeTransform (Matrix4 worldTransform) {
float[] val=worldTransform.getValues();
//val[Matrix4.M32]=0.0002f;
worldTransform.set(val);
float originX = this.getOriginX(), originY = this.getOriginY();
worldTransform.translate(getX()+getWidth()/2 , getY()+getHeight()/2,0);
if(clicked)
{
worldTransform.rotate(0,1,0,180*flipProcess);
}
computedTransform.set(worldTransform);
return computedTransform;
}
}

View File

@@ -0,0 +1,13 @@
package forge.adventure.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* Interface to save the content the the save game file
*/
public interface SaveFileContent {
void writeToSaveFile(ObjectOutputStream saveFile) throws IOException ;
void readFromSaveFile(ObjectInputStream saveFile) throws IOException, ClassNotFoundException;
}

View File

@@ -0,0 +1,109 @@
package forge.adventure.util;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Pools;
/**
* UI element to click through options, can be configured in an UiActor
*/
public class Selector extends Group {
private final ImageButton leftArrow;
private final ImageButton rightArrow;
private final TextButton label;
private int currentIndex = 0;
private Array<String> textList;
public Selector() {
ImageButton.ImageButtonStyle leftArrowStyle = Controls.GetSkin().get("leftarrow", ImageButton.ImageButtonStyle.class);
leftArrow = new ImageButton(leftArrowStyle);
ImageButton.ImageButtonStyle rightArrowStyle = Controls.GetSkin().get("rightarrow", ImageButton.ImageButtonStyle.class);
rightArrow = new ImageButton(rightArrowStyle);
label = new TextButton("", Controls.GetSkin());
addActor(leftArrow);
addActor(rightArrow);
addActor(label);
leftArrow.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
try {
setCurrentIndex(currentIndex - 1);
} catch (Exception e) {
e.printStackTrace();
}
}
});
rightArrow.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
try {
setCurrentIndex(currentIndex + 1);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
@Override
protected void sizeChanged() {
super.sizeChanged();
leftArrow.setWidth(getHeight());
leftArrow.setHeight(getHeight());
rightArrow.setWidth(getHeight());
rightArrow.setHeight(getHeight());
label.setHeight(getHeight());
label.setX(getHeight());
label.setWidth(getWidth() - (getHeight() * 2));
rightArrow.setX(getWidth() - getHeight());
}
public int getCurrentIndex() {
return currentIndex;
}
public void setCurrentIndex(int currentIndex) {
currentIndex %= textList.size;
if (currentIndex < 0) {
currentIndex += textList.size;
}
int oldIndex = currentIndex;
this.currentIndex = currentIndex;
label.setText(textList.get(currentIndex));
ChangeListener.ChangeEvent changeEvent = Pools.obtain(ChangeListener.ChangeEvent.class);
if (fire(changeEvent)) {
this.currentIndex = oldIndex;
label.setText(textList.get(currentIndex));
}
Pools.free(changeEvent);
}
public String getText() {
return textList.get(currentIndex);
}
public Array<String> getTextList() {
return textList;
}
public void setTextList(Array<String> textList) {
this.textList = textList;
setCurrentIndex(currentIndex);
}
public void setTextList(String[] strings) {
this.textList = new Array<>(strings);
setCurrentIndex(currentIndex);
}
}

View File

@@ -0,0 +1,83 @@
package forge.adventure.util;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.PixmapIO;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* Abstract class to serialize other objects.
*/
public abstract class Serializer {
static public void WritePixmap(java.io.ObjectOutputStream out, Pixmap pixmap) throws IOException {
if (pixmap != null) {
PixmapIO.PNG png = new PixmapIO.PNG();
png.setFlipY(false);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
png.write(stream, pixmap);
byte[] data = stream.toByteArray();
out.writeInt(data.length);
out.write(data);
} else {
out.writeInt(0);
}
}
static public Pixmap ReadPixmap(ObjectInputStream in) throws IOException, ClassNotFoundException {
int length = in.readInt();
if (length == 0)
return new Pixmap(1, 1, Pixmap.Format.RGBA8888);
byte[] data = new byte[length];
in.readFully(data, 0, length);
return new Pixmap(data, 0, length);
}
public static void WritePixmap(ObjectOutputStream out, Pixmap pixmap, boolean b) throws IOException {
if (pixmap != null) {
PixmapIO.PNG png = new PixmapIO.PNG();
png.setFlipY(b);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
png.write(stream, pixmap);
byte[] data = stream.toByteArray();
out.writeInt(data.length);
out.write(data);
} else {
out.writeInt(0);
}
}
public static void writeVector(ObjectOutputStream out,Vector2 position) throws IOException {
out.writeFloat(position.x);
out.writeFloat(position.y);
}
public static void readVector(ObjectInputStream in, Vector2 position) throws IOException {
float x=in.readFloat();
position.set(x,in.readFloat());
}
public static void writeRectangle(ObjectOutputStream out,Rectangle rectangle) throws IOException {
out.writeFloat(rectangle.x);
out.writeFloat(rectangle.y);
out.writeFloat(rectangle.width);
out.writeFloat(rectangle.height);
}
public static void readRectangle(ObjectInputStream in, Rectangle rectangle) throws IOException {
float x=in.readFloat();
float y=in.readFloat();
float w=in.readFloat();
float h=in.readFloat();
rectangle.set(x,y,w,h);
}
}

View File

@@ -0,0 +1,19 @@
package forge.adventure.util;
import com.badlogic.gdx.utils.Array;
/**
* List of function points to inform all listeners, maybe redesign to a more java like approach
*/
public class SignalList extends Array<Runnable> {
public void emit() {
for(Runnable signal:this) {
try {
signal.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,55 @@
package forge.adventure.util;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.maps.ImageResolver;
import com.badlogic.gdx.maps.MapObjects;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.XmlReader;
/**
* Rewritten the loadObject method of TmxMapLoader to support templates in tiled map.
*
*/
public class TemplateTmxMapLoader extends TmxMapLoader {
FileHandle tmxFile;
@Override
protected TiledMap loadTiledMap(FileHandle tmxFile, TmxMapLoader.Parameters parameter, ImageResolver imageResolver) {
this.tmxFile = tmxFile;
return super.loadTiledMap(tmxFile, parameter, imageResolver);
}
@Override
protected void loadObject(TiledMap map, MapObjects objects, XmlReader.Element element, float heightInPixels) {
if (element.getName().equals("object")) {
if (!element.hasAttribute("template")) {
super.loadObject(map, objects, element, heightInPixels);
return;
}
FileHandle template = getRelativeFileHandle(tmxFile, element.getAttribute("template"));
XmlReader.Element el = xml.parse(template);
for (XmlReader.Element obj : new Array.ArrayIterator<>(el.getChildrenByName("object"))) {
for(ObjectMap.Entry<String, String> attr: new ObjectMap.Entries<>(element.getAttributes()))
{
obj.setAttribute(attr.key, attr.value);
}
XmlReader.Element properties = element.getChildByName("properties");
XmlReader.Element templateProperties = obj.getChildByName("properties");
if (properties != null&&templateProperties!=null)
{
for( XmlReader.Element propertyElements : new Array.ArrayIterator<>(properties.getChildrenByName("property")))
{
templateProperties.addChild(propertyElements);
}
}
super.loadObject(map, objects, obj, heightInPixels);
return;
}
}
}
}

View File

@@ -0,0 +1,192 @@
package forge.adventure.util;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.OrderedMap;
import forge.adventure.data.UIData;
/**
* Group of controls that will be loaded from a configuration file
*/
public class UIActor extends Group {
UIData data;
public UIActor(FileHandle handle) {
data = (new Json()).fromJson(UIData.class, handle);
setWidth(data.width);
setHeight(data.height);
for (OrderedMap<String, String> element : new Array.ArrayIterator<>(data.elements)) {
String type = element.get("type");
Actor newActor;
if(type==null)
{
newActor=new Actor();
}
else
{
switch (type) {
case "Selector":
newActor = new Selector();
readSelectorProperties((Selector) newActor, new OrderedMap.OrderedMapEntries<>(element));
break;
case "Label":
newActor = new Label("", Controls.GetSkin());
readLabelProperties((Label) newActor, new OrderedMap.OrderedMapEntries<>(element));
break;
case "Image":
newActor = new Image();
readImageProperties((Image) newActor, new OrderedMap.OrderedMapEntries<>(element));
break;
case "ImageButton":
newActor = new ImageButton(Controls.GetSkin());
readImageButtonProperties((ImageButton) newActor, new OrderedMap.OrderedMapEntries<>(element));
break;
case "Window":
newActor = new Window("", Controls.GetSkin());
readWindowProperties((Window) newActor, new OrderedMap.OrderedMapEntries<>(element));
break;
case "TextButton":
newActor = new TextButton("", Controls.GetSkin());
readButtonProperties((TextButton) newActor, new OrderedMap.OrderedMapEntries<>(element));
break;
case "TextField":
newActor = new TextField("", Controls.GetSkin());
readTextFieldProperties((TextField) newActor, new OrderedMap.OrderedMapEntries<>(element));
break;
case "Scroll":
newActor = new ScrollPane(null, Controls.GetSkin());
readScrollPaneProperties((ScrollPane) newActor, new OrderedMap.OrderedMapEntries<>(element));
break;
default:
throw new IllegalStateException("Unexpected value: " + type);
}
}
//load Actor Properties
float yValue = 0;
for (ObjectMap.Entry property : new OrderedMap.OrderedMapEntries<>(element)) {
switch (property.key.toString()) {
case "width":
newActor.setWidth((Float) property.value);
break;
case "height":
newActor.setHeight((Float) property.value);
if (data.yDown)
newActor.setY(data.height - yValue - newActor.getHeight());
break;
case "x":
newActor.setX((Float) property.value);
break;
case "y":
yValue = (Float) property.value;
newActor.setY(data.yDown ? data.height - yValue - newActor.getHeight() : yValue);
break;
case "name":
newActor.setName((String) property.value);
break;
}
}
addActor(newActor);
}
}
private void readScrollPaneProperties(ScrollPane newActor, ObjectMap.Entries<String, String> entries) {
newActor.setActor(new Label("",Controls.GetSkin()));
for (ObjectMap.Entry property : entries) {
switch (property.key.toString()) {
case "style":
newActor.setStyle(Controls.GetSkin().get(property.value.toString(), ScrollPane.ScrollPaneStyle.class));
break;
}
}
}
private void readWindowProperties(Window newActor, ObjectMap.Entries<String, String> entries) {
for (ObjectMap.Entry property : entries) {
switch (property.key.toString()) {
case "style":
newActor.setStyle(Controls.GetSkin().get(property.value.toString(), Window.WindowStyle.class));
break;
}
}
}
private void readTextFieldProperties(TextField newActor, ObjectMap.Entries<String, String> entries) {
for (ObjectMap.Entry property : entries) {
switch (property.key.toString()) {
case "text":
newActor.setText(property.value.toString());
break;
}
}
}
private void readImageButtonProperties(ImageButton newActor, ObjectMap.Entries<String, String> entries) {
for (ObjectMap.Entry property : entries) {
switch (property.key.toString()) {
case "style":
newActor.setStyle(Controls.GetSkin().get(property.value.toString(), ImageButton.ImageButtonStyle.class));
break;
}
}
}
private void readLabelProperties(Label newActor, ObjectMap.Entries<String, String> entries) {
for (ObjectMap.Entry property : entries) {
switch (property.key.toString()) {
case "text":
newActor.setText(property.value.toString());
break;
case "font":
Label.LabelStyle style = new Label.LabelStyle(newActor.getStyle());
style.font = Controls.GetSkin().getFont(property.value.toString());
newActor.setStyle(style);
break;
}
}
}
private void readSelectorProperties(Selector newActor, ObjectMap.Entries<String, String> entries) {
}
private void readButtonProperties(TextButton newActor, ObjectMap.Entries<String, String> entries) {
for (ObjectMap.Entry property : entries) {
switch (property.key.toString()) {
case "text":
newActor.setText(property.value.toString());
break;
}
}
}
private void readImageProperties(Image newActor, ObjectMap.Entries<String, String> entries) {
for (ObjectMap.Entry property : entries) {
switch (property.key.toString()) {
case "image":
newActor.setDrawable(new TextureRegionDrawable(new Texture(Config.instance().getFile(property.value.toString()))));
break;
}
}
}
public void onButtonPress(String name, Runnable func) {
Actor button = findActor(name);
assert button != null;
button.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
func.run();
}
});
}
}

View File

@@ -0,0 +1,215 @@
package forge.adventure.world;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Disposable;
import forge.adventure.data.DifficultyData;
import forge.adventure.data.HeroListData;
import forge.adventure.util.Config;
import forge.adventure.util.Reward;
import forge.adventure.util.SaveFileContent;
import forge.adventure.util.SignalList;
import forge.deck.Deck;
import forge.item.PaperCard;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Class that represents the player (not the player sprite)
*/
public class AdventurePlayer implements Serializable, Disposable, SaveFileContent {
private Deck deck;
private int avatarIndex;
private int heroRace;
private boolean isFemale;
private float worldPosX;
private float worldPosY;
private String name;
private int gold=0;
private int maxLife=20;
private int life=20;
private DifficultyData difficultyData;
static public AdventurePlayer current()
{
return WorldSave.currentSave.getPlayer();
}
private List<PaperCard> cards=new ArrayList<>();
public void create(String n, Deck startingDeck, boolean male, int race, int avatar,DifficultyData difficultyData) {
deck = startingDeck;
gold =difficultyData.staringMoney;
cards.addAll(deck.getAllCardsInASinglePool().toFlatList());
maxLife=difficultyData.startingLife;
this.difficultyData=difficultyData;
life=maxLife;
avatarIndex = avatar;
heroRace = race;
isFemale = !male;
name = n;
onGoldChangeList.emit();
onLifeTotalChangeList.emit();
}
public Deck getDeck() {
return deck;
}
public List<PaperCard> getCards() {
return cards;
}
public String getName() {
return name;
}
public float getWorldPosX() {
return worldPosX;
}
public void setWorldPosX(float worldPosX) {
this.worldPosX = worldPosX;
}
public float getWorldPosY() {
return worldPosY;
}
public void setWorldPosY(float worldPosY) {
this.worldPosY = worldPosY;
}
@Override
public void writeToSaveFile(java.io.ObjectOutputStream out) throws IOException {
out.writeUTF(name);
out.writeFloat(worldPosX);
out.writeFloat(worldPosY);
out.writeInt(avatarIndex);
out.writeInt(heroRace);
out.writeBoolean(isFemale);
out.writeInt(gold);
out.writeInt(life);
out.writeInt(maxLife);
out.writeObject(deck);
out.writeObject(cards);
}
@Override
public void readFromSaveFile(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
name = in.readUTF();
worldPosX = in.readFloat();
worldPosY = in.readFloat();
avatarIndex = in.readInt();
heroRace = in.readInt();
isFemale = in.readBoolean();
gold = in.readInt();
life = in.readInt();
maxLife = in.readInt();
deck = (Deck) in.readObject();
cards = (List) in.readObject();
onLifeTotalChangeList.emit();
onGoldChangeList.emit();
}
public void dispose() {
}
public String spriteName() {
return HeroListData.getHero(heroRace, isFemale);
}
public FileHandle sprite() {
return Config.instance().getFile(HeroListData.getHero(heroRace, isFemale));
}
public TextureRegion avatar() {
return HeroListData.getAvatar(heroRace, isFemale, avatarIndex);
}
public void addReward(Reward reward) {
switch (reward.getType())
{
case Card:
cards.add(reward.getCard());
break;
case Gold:
addGold(reward.getCount());
break;
case Item:
break;
case Life:
addMaxLife(reward.getCount());
break;
}
}
SignalList onLifeTotalChangeList=new SignalList();
SignalList onGoldChangeList=new SignalList();
SignalList onPlayerChangeList=new SignalList();
private void addGold(int goldCount) {
gold+=goldCount;
onGoldChangeList.emit();
}
public int getGold() {
return gold;
}
public void onLifeChange(Runnable o) {
onLifeTotalChangeList.add(o);
o.run();
}
public void onPlayerChanged(Runnable o) {
onPlayerChangeList.add(o);
o.run();
}
public void onGoldChange(Runnable o) {
onGoldChangeList.add(o);
o.run();
}
public int getLife() {
return life;
}
public int getMaxLife() {
return maxLife;
}
public void heal() {
life=maxLife;
onLifeTotalChangeList.emit();
}
public void defeated() {
gold=gold/2;
life=Math.max(1,(int)(life-(maxLife*0.2f)));
onLifeTotalChangeList.emit();
onGoldChangeList.emit();
}
public void addMaxLife(int count) {
maxLife+=count;
life+=count;
onLifeTotalChangeList.emit();
}
public void takeGold(int price) {
gold-=price;
onGoldChangeList.emit();
}
public DifficultyData getDifficulty() {
return difficultyData;
}
}

View File

@@ -0,0 +1,46 @@
package forge.adventure.world;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectSet;
import forge.adventure.data.BiomeSpriteData;
import forge.adventure.util.Config;
import java.util.HashMap;
/**
* class to load and buffer map sprites
*/
public class BiomeSprites {
private final HashMap<String, Array<Sprite>> spriteBuffer = new HashMap<>();
public String textureAtlas;
public BiomeSpriteData[] sprites;
private TextureAtlas textureAtlasBuffer;
public Sprite getSprite(String name, int seed) {
if (textureAtlasBuffer == null) {
textureAtlasBuffer = Config.instance().getAtlas(textureAtlas);
for (Texture texture : new ObjectSet.ObjectSetIterator<>(textureAtlasBuffer.getTextures())) {
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
}
}
if (!spriteBuffer.containsKey(name)) {
spriteBuffer.put(name, new Array<Sprite>());
}
Array<Sprite> sprites = spriteBuffer.get(name);
if (sprites.isEmpty()) {
sprites.addAll(textureAtlasBuffer.createSprites(name));
}
return sprites.get(seed % sprites.size);
}
public BiomeSpriteData getSpriteData(String name) {
for (BiomeSpriteData data : sprites) {
if (data.name.equals(name))
return data;
}
return null;
}
}

Some files were not shown because too many files have changed in this diff Show More