Merge branch 'Card-Forge:master' into master

This commit is contained in:
Suthro
2022-08-08 22:55:18 -05:00
committed by GitHub
123 changed files with 4934 additions and 1191 deletions

View File

@@ -17,7 +17,7 @@
</repository>
</repositories>
<build>
<sourceDirectory>src</sourceDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<resources>
<resource>
<directory>${project.basedir}</directory>

View File

@@ -2,11 +2,7 @@ package forge.adventure;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
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.backends.lwjgl3.Lwjgl3Window;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3WindowListener;
import com.badlogic.gdx.backends.lwjgl3.*;
import com.badlogic.gdx.graphics.glutils.HdpiMode;
import forge.Forge;
import forge.adventure.util.Config;
@@ -107,7 +103,13 @@ public class Main {
}
});
for(int i=0;i<args.length;i++)
{
if(args[i].equals("testMap"))
{
Forge.createNewAdventureMap=true;
}
}
new Lwjgl3Application(start, config);
}

View File

@@ -0,0 +1,125 @@
package forge.adventure.editor;
import forge.adventure.data.BiomeData;
import javax.swing.*;
public class BiomeEdit extends FormPanel {
BiomeData currentData;
public JSpinner startPointX= new JSpinner(new SpinnerNumberModel(0.0f, 0.f, 1f, 0.1f));
public JSpinner startPointY= new JSpinner(new SpinnerNumberModel(0.0f, 0.f, 1f, 0.1f));
public JSpinner noiseWeight= new JSpinner(new SpinnerNumberModel(0.0f, 0.f, 1f, 0.1f));
public JSpinner distWeight= new JSpinner(new SpinnerNumberModel(0.0f, 0.f, 1f, 0.1f));
public JTextField name=new JTextField();
public FilePicker tilesetAtlas=new FilePicker(new String[]{"atlas"});
public JTextField tilesetName=new JTextField();
public JSpinner width= new JSpinner(new SpinnerNumberModel(0.0f, 0.f, 1f, 0.1f));
public JSpinner height= new JSpinner(new SpinnerNumberModel(0.0f, 0.f, 1f, 0.1f));
public JTextField color=new JTextField();
public JCheckBox collision=new JCheckBox();
public TextListEdit spriteNames =new TextListEdit();
public TextListEdit enemies =new TextListEdit();
public TextListEdit pointsOfInterest =new TextListEdit();
public TerrainsEditor terrain =new TerrainsEditor();
public StructureEditor structures =new StructureEditor();
private boolean updating=false;
public BiomeEdit()
{
FormPanel center=new FormPanel() { };
center.add("startPointX:",startPointX);
center.add("startPointY:",startPointY);
center.add("noiseWeight:",noiseWeight);
center.add("distWeight:",distWeight);
center.add("name:",name);
center.add("tilesetAtlas:",tilesetAtlas);
center.add("tilesetName:",tilesetName);
center.add("width:",width);
center.add("height:",height);
center.add("spriteNames:",spriteNames);
center.add("enemies:",enemies);
center.add("pointsOfInterest:",pointsOfInterest);
center.add("color:",color);
center.add("collision:",collision);
center.add("terrain/structures:",new JLabel(""));
add(center);
add(terrain);
add(structures);
name.getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeEdit.this.updateTerrain()));
tilesetName.getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeEdit.this.updateTerrain()));
color.getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeEdit.this.updateTerrain()));
collision.addChangeListener(e -> BiomeEdit.this.updateTerrain());
spriteNames.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeEdit.this.updateTerrain()));
enemies.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeEdit.this.updateTerrain()));
terrain.addChangeListener(e -> BiomeEdit.this.updateTerrain());
startPointX.addChangeListener(e -> BiomeEdit.this.updateTerrain());
startPointY.addChangeListener(e -> BiomeEdit.this.updateTerrain());
noiseWeight.addChangeListener(e -> BiomeEdit.this.updateTerrain());
distWeight.addChangeListener(e -> BiomeEdit.this.updateTerrain());
tilesetAtlas.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeEdit.this.updateTerrain()));
width.addChangeListener(e -> BiomeEdit.this.updateTerrain());
height.addChangeListener(e -> BiomeEdit.this.updateTerrain());
refresh();
}
protected void updateTerrain() {
if(currentData==null||updating)
return;
currentData.startPointX = (Float) startPointX.getValue();
currentData.startPointY = (Float) startPointY.getValue();
currentData.noiseWeight = (Float) noiseWeight.getValue();
currentData.distWeight = (Float)distWeight.getValue();
currentData.name = name.getText();
currentData.tilesetAtlas = tilesetAtlas.edit.getText();
currentData.tilesetName = tilesetName.getText();
currentData.terrain = terrain.getBiomeTerrainData();
currentData.structures = structures.getBiomeStructureData();
currentData.width = (Float) width.getValue();
currentData.height = (Float) height.getValue();
currentData.color = color.getText();
currentData.collision = collision.isSelected();
currentData.spriteNames = spriteNames.getList();
currentData.enemies = enemies.getList();
currentData.pointsOfInterest = pointsOfInterest.getList();
}
public void setCurrentBiome(BiomeData data)
{
currentData=data;
refresh();
}
private void refresh() {
setEnabled(currentData!=null);
if(currentData==null)
{
return;
}
updating=true;
startPointX.setValue(currentData.startPointX);
startPointY.setValue(currentData.startPointY);
noiseWeight.setValue(currentData.noiseWeight);
distWeight.setValue(currentData.distWeight);
name.setText(currentData.name);
tilesetAtlas.edit.setText( currentData.tilesetAtlas);
tilesetName.setText(currentData.tilesetName);
terrain.setTerrains(currentData);
structures.setStructures(currentData);
width.setValue(currentData.width);
height.setValue(currentData.height);
color.setText(currentData.color);
spriteNames.setText(currentData.spriteNames);
enemies.setText(currentData.enemies);
collision.setSelected(currentData.collision);
pointsOfInterest.setText(currentData.pointsOfInterest);
updating=false;
}
}

View File

@@ -0,0 +1,171 @@
package forge.adventure.editor;
import forge.adventure.data.BiomeStructureData;
import forge.adventure.util.Config;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class BiomeStructureDataMappingEditor extends JComponent {
DefaultListModel<BiomeStructureData.BiomeStructureDataMapping> model = new DefaultListModel<>();
JList<BiomeStructureData.BiomeStructureDataMapping> list = new JList<>(model);
JToolBar toolBar = new JToolBar("toolbar");
BiomeStructureDataMappingEdit edit=new BiomeStructureDataMappingEdit();
private BiomeStructureData data;
public void setCurrent(BiomeStructureData data) {
this.data=data;
model.clear();
if(data==null||data.mappingInfo==null)
return;
for(int i=0;i<data.mappingInfo.length;i++)
model.addElement(data.mappingInfo[i]);
list.setSelectedIndex(0);
}
public BiomeStructureData.BiomeStructureDataMapping[] getCurrent()
{
BiomeStructureData.BiomeStructureDataMapping[] array=new BiomeStructureData.BiomeStructureDataMapping[model.size()];
for(int i=0;i<array.length;i++)
array[i]=model.get(i);
return array;
}
public class BiomeStructureDataMappingRenderer extends DefaultListCellRenderer {
private final BiomeStructureDataMappingEditor editor;
public BiomeStructureDataMappingRenderer(BiomeStructureDataMappingEditor biomeStructureDataMappingEditor) {
this.editor=biomeStructureDataMappingEditor;
}
@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 BiomeStructureData.BiomeStructureDataMapping))
return label;
BiomeStructureData.BiomeStructureDataMapping data=(BiomeStructureData.BiomeStructureDataMapping) value;
// Get the renderer component from parent class
label.setText(data.name);
if(editor.data!=null)
{
SwingAtlas itemAtlas=new SwingAtlas(Config.instance().getFile(editor.data.structureAtlasPath));
if(itemAtlas.has(data.name))
label.setIcon(itemAtlas.get(data.name));
else
{
ImageIcon img=itemAtlas.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 BiomeStructureDataMappingEditor()
{
list.setCellRenderer(new BiomeStructureDataMappingEditor.BiomeStructureDataMappingRenderer(this));
list.addListSelectionListener(e -> BiomeStructureDataMappingEditor.this.updateEdit());
addButton("add", e -> BiomeStructureDataMappingEditor.this.add());
addButton("remove", e -> BiomeStructureDataMappingEditor.this.remove());
addButton("copy", e -> BiomeStructureDataMappingEditor.this.copy());
BorderLayout layout=new BorderLayout();
setLayout(layout);
add(new JScrollPane(list), BorderLayout.WEST);
add(toolBar, BorderLayout.NORTH);
add(edit,BorderLayout.CENTER);
}
private void copy() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
BiomeStructureData.BiomeStructureDataMapping data=new BiomeStructureData.BiomeStructureDataMapping(model.get(selected));
model.add(model.size(),data);
}
private void updateEdit() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
edit.setCurrent(model.get(selected));
}
void add()
{
BiomeStructureData.BiomeStructureDataMapping data=new BiomeStructureData.BiomeStructureDataMapping();
data.name="Structure "+model.getSize();
model.add(model.size(),data);
}
void remove()
{
int selected=list.getSelectedIndex();
if(selected<0)
return;
model.remove(selected);
}
private class BiomeStructureDataMappingEdit extends FormPanel{
BiomeStructureData.BiomeStructureDataMapping currentData;
public JTextField name=new JTextField();
public JTextField color=new JTextField();
public JCheckBox collision=new JCheckBox();
private boolean updating=false;
public BiomeStructureDataMappingEdit()
{
add("name:",name);
add("color:",color);
add("collision:",collision);
name.getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeStructureDataMappingEdit.this.update()));
color.getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeStructureDataMappingEdit.this.update()));
collision.addChangeListener(e -> BiomeStructureDataMappingEdit.this.update());
refresh();
}
private void update() {
if(currentData==null||updating)
return;
currentData.name = name.getText();
currentData.color = color.getText();
currentData.collision = collision.isSelected();
}
public void setCurrent(BiomeStructureData.BiomeStructureDataMapping data)
{
currentData=data;
refresh();
}
private void refresh() {
setEnabled(currentData!=null);
if(currentData==null)
{
return;
}
updating=true;
name.setText(currentData.name);
color.setText(currentData.color);
collision.setSelected(currentData.collision);
updating=false;
}
}
}

View File

@@ -0,0 +1,136 @@
package forge.adventure.editor;
import forge.adventure.data.BiomeData;
import forge.adventure.data.BiomeStructureData;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class BiomeStructureEdit extends FormPanel {
private boolean updating=false;
BiomeStructureData currentData;
BiomeData currentBiomeData;
public JTextField structureAtlasPath=new JTextField();
public FloatSpinner x= new FloatSpinner();
public FloatSpinner y= new FloatSpinner();
public FloatSpinner width= new FloatSpinner();
public FloatSpinner height= new FloatSpinner();
public JCheckBox randomPosition=new JCheckBox();
public IntSpinner N= new IntSpinner();
public JTextField sourcePath= new JTextField();
public JTextField maskPath= new JTextField();
public JCheckBox periodicInput= new JCheckBox();
public IntSpinner ground= new IntSpinner();
public IntSpinner symmetry= new IntSpinner();
public JCheckBox periodicOutput= new JCheckBox();
public BiomeStructureDataMappingEditor data=new BiomeStructureDataMappingEditor();
public BiomeStructureEdit()
{
FormPanel center=new FormPanel();
center.add("structureAtlasPath:",structureAtlasPath);
center.add("x:",x);
center.add("y:",y);
center.add("width:",width);
center.add("height:",height);
center.add("N:",N);
center.add("sourcePath:",sourcePath);
center.add("maskPath:",maskPath);
center.add("periodicInput:",periodicInput);
center.add("ground:",ground);
center.add("symmetry:",symmetry);
center.add("periodicOutput:",periodicOutput);
add(center);
add(data);
structureAtlasPath.getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeStructureEdit.this.updateStructure()));
x.addChangeListener(e -> BiomeStructureEdit.this.updateStructure());
y.addChangeListener(e -> BiomeStructureEdit.this.updateStructure());
width.addChangeListener(e -> BiomeStructureEdit.this.updateStructure());
height.addChangeListener(e -> BiomeStructureEdit.this.updateStructure());
randomPosition.addChangeListener(e -> BiomeStructureEdit.this.updateStructure());
N.addChangeListener(e -> BiomeStructureEdit.this.updateStructure());
sourcePath.getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeStructureEdit.this.updateStructure()));
maskPath.getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeStructureEdit.this.updateStructure()));
periodicInput.addChangeListener(e -> BiomeStructureEdit.this.updateStructure());
ground.addChangeListener(e -> BiomeStructureEdit.this.updateStructure());
symmetry.addChangeListener(e -> BiomeStructureEdit.this.updateStructure());
periodicOutput.addChangeListener(e -> BiomeStructureEdit.this.updateStructure());
refresh();
}
private void refresh() {
setEnabled(currentData!=null);
if(currentData==null)
{
data.setCurrent(null);
return;
}
updating=true;
structureAtlasPath.setText(currentData.structureAtlasPath);
x.setValue(currentData.x);
y.setValue(currentData.y);
width.setValue(currentData.width);
height.setValue(currentData.height);
randomPosition.setSelected(currentData.randomPosition);
N.setValue(currentData.N);
sourcePath.setText(currentData.sourcePath);
maskPath.setText(currentData.maskPath);
periodicInput.setSelected(currentData.periodicInput);
ground.setValue(currentData.ground);
symmetry.setValue(currentData.symmetry);
periodicOutput.setSelected(currentData.periodicOutput);
data.setCurrent(currentData);
updating=false;
}
public void updateStructure()
{
if(currentData==null||updating)
return;
currentData.structureAtlasPath=structureAtlasPath.getText();
currentData.x= x.floatValue();
currentData.y= y.floatValue();
currentData.width= width.floatValue();
currentData.height= height.floatValue();
currentData.randomPosition=randomPosition.isSelected();
currentData.mappingInfo= data.getCurrent();
currentData.N= N.intValue();
currentData.sourcePath= sourcePath.getText();
currentData.maskPath= maskPath.getText();
currentData.periodicInput= periodicInput.isSelected();
currentData.ground= ground.intValue();
currentData.symmetry= symmetry.intValue();
currentData.periodicOutput= periodicOutput.isSelected();
emitChanged();
}
public void setCurrentStructure(BiomeStructureData biomeTerrainData, BiomeData data) {
currentData =biomeTerrainData;
currentBiomeData=data;
refresh();
}
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
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);
}
}
}
}

View File

@@ -0,0 +1,84 @@
package forge.adventure.editor;
import forge.adventure.data.BiomeData;
import forge.adventure.data.BiomeTerrainData;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class BiomeTerrainEdit extends FormPanel {
SwingAtlasPreview preview=new SwingAtlasPreview(128);
private boolean updating=false;
BiomeTerrainData currentData;
BiomeData currentBiomeData;
public JTextField spriteName=new JTextField();
public JSpinner min= new JSpinner(new SpinnerNumberModel(0.0f, 0.f, 1f, 0.1f));
public JSpinner max= new JSpinner(new SpinnerNumberModel(0.0f, 0.f, 1f, 0.1f));
public JSpinner resolution= new JSpinner(new SpinnerNumberModel(0.0f, 0.f, 1f, 0.1f));
public BiomeTerrainEdit()
{
FormPanel center=new FormPanel() { };
center.add("spriteName:",spriteName);
center.add("min:",min);
center.add("max:",max);
center.add("resolution:",resolution);
add(center,preview);
spriteName.getDocument().addDocumentListener(new DocumentChangeListener(() -> BiomeTerrainEdit.this.updateTerrain()));
min.addChangeListener(e -> BiomeTerrainEdit.this.updateTerrain());
max.addChangeListener(e -> BiomeTerrainEdit.this.updateTerrain());
resolution.addChangeListener(e -> BiomeTerrainEdit.this.updateTerrain());
refresh();
}
private void refresh() {
setEnabled(currentData!=null);
if(currentData==null)
{
return;
}
updating=true;
spriteName.setText(currentData.spriteName);
min.setValue(currentData.min);
max.setValue(currentData.max);
resolution.setValue(currentData.resolution);
if(currentBiomeData!=null&&currentData!= null)
preview.setSpritePath(currentBiomeData.tilesetAtlas,currentData.spriteName);
updating=false;
}
public void updateTerrain()
{
if(currentData==null||updating)
return;
currentData.spriteName=spriteName.getText();
currentData.min= (float) min.getValue();
currentData.max= (float) max.getValue();
currentData.resolution= (float) resolution.getValue();
preview.setSpritePath(currentBiomeData.tilesetAtlas,currentData.spriteName);
emitChanged();
}
public void setCurrentTerrain(BiomeTerrainData biomeTerrainData, BiomeData data) {
currentData =biomeTerrainData;
currentBiomeData=data;
refresh();
}
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
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);
}
}
}
}

View File

@@ -7,6 +7,7 @@ import java.awt.*;
* Editor class to edit configuration, maybe moved or removed
*/
public class EditorMainWindow extends JFrame {
public final static WorldEditor worldEditor = new WorldEditor();
JTabbedPane tabs =new JTabbedPane();
public EditorMainWindow()
@@ -14,8 +15,8 @@ public class EditorMainWindow extends JFrame {
BorderLayout layout=new BorderLayout();
setLayout(layout);
add(tabs);
tabs.addTab("World",worldEditor);
tabs.addTab("POI",new PointOfInterestEditor());
tabs.addTab("World",new WorldEditor());
tabs.addTab("Items",new ItemsEditor());
tabs.addTab("Enemies",new EnemyEditor());
setVisible(true);

View File

@@ -5,7 +5,6 @@ import forge.adventure.data.EffectData;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
public class EffectEditor extends JComponent {
EffectData currentData;
@@ -25,16 +24,15 @@ public class EffectEditor extends JComponent {
if(!isOpponentEffect)
opponent=new EffectEditor(true);
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
JPanel parameters=new JPanel();
FormPanel parameters=new FormPanel();
parameters.setBorder(BorderFactory.createTitledBorder("Effect"));
parameters.setLayout(new GridLayout(7,2)) ;
parameters.add(new JLabel("Name:")); parameters.add(name);
parameters.add(new JLabel("Start with extra cards:")); parameters.add(changeStartCards);
parameters.add(new JLabel("Change life:")); parameters.add(lifeModifier);
parameters.add(new JLabel("Movement speed:")); parameters.add(moveSpeed);
parameters.add(new JLabel("Start battle with cards:")); parameters.add(startBattleWithCard);
parameters.add(new JLabel("color view:")); parameters.add(colorView);
parameters.add("Name:", name);
parameters.add("Start with extra cards:", changeStartCards);
parameters.add("Change life:", lifeModifier);
parameters.add("Movement speed:", moveSpeed);
parameters.add("Start battle with cards:", startBattleWithCard);
parameters.add("color view:", colorView);
add(parameters);
if(!isOpponentEffect)
{ add(new JLabel("Opponent:")); add(opponent);}

View File

@@ -3,21 +3,21 @@ 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 {
public class EnemyEdit extends FormPanel {
EnemyData currentData;
JTextField nameField=new JTextField();
JTextField colorField=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));
JTextField ai=new JTextField();
JCheckBox flying=new JCheckBox();
JCheckBox boss=new JCheckBox();
FloatSpinner lifeFiled= new FloatSpinner(0, 1000, 1);
FloatSpinner spawnRate= new FloatSpinner( 0.f, 1, 0.1f);
FloatSpinner difficulty= new FloatSpinner( 0.f, 1, 0.1f);
FloatSpinner speed= new FloatSpinner( 0.f, 100.f, 1.0f);
FilePicker deck=new FilePicker(new String[]{"dck","json"});
FilePicker atlas=new FilePicker(new String[]{"atlas"});
JTextField equipment=new JTextField();
@@ -28,27 +28,34 @@ public class EnemyEdit extends JComponent {
public EnemyEdit()
{
JComponent center=new JComponent() { };
center.setLayout(new GridLayout(9,2));
FormPanel center=new FormPanel() { };
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);
center.add(new JLabel("Equipment:")); center.add(equipment);
center.add(new JLabel("Colors:")); center.add(colorField);
BorderLayout layout=new BorderLayout();
setLayout(layout);
add(center,BorderLayout.PAGE_START);
add(rewards,BorderLayout.CENTER);
add(preview,BorderLayout.LINE_START);
center.add("Name:",nameField);
center.add("Life:",lifeFiled);
center.add("Spawn rate:",spawnRate);
center.add("Difficulty:",difficulty);
center.add("Speed:",speed);
center.add("Deck:",deck);
center.add("Sprite:",atlas);
center.add("Equipment:",equipment);
center.add("Colors:",colorField);
center.add("ai:",ai);
center.add("flying:",flying);
center.add("boss:",boss);
add(preview);
add(center);
add(rewards);
equipment.getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
atlas.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
colorField.getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
ai.getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
flying.addChangeListener(e -> EnemyEdit.this.updateEnemy());
boss.addChangeListener(e -> EnemyEdit.this.updateEnemy());
nameField.getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
deck.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
lifeFiled.addChangeListener(e -> EnemyEdit.this.updateEnemy());
@@ -65,6 +72,9 @@ public class EnemyEdit extends JComponent {
return;
currentData.name=nameField.getText();
currentData.colors=colorField.getText();
currentData.ai=ai.getText();
currentData.flying=flying.isSelected();
currentData.boss=boss.isSelected();
currentData.life= (int) lifeFiled.getValue();
currentData.sprite= atlas.getEdit().getText();
if(equipment.getText().isEmpty())
@@ -94,6 +104,9 @@ public class EnemyEdit extends JComponent {
updating=true;
nameField.setText(currentData.name);
colorField.setText(currentData.colors);
ai.setText(currentData.ai);
boss.setSelected(currentData.boss);
flying.setSelected(currentData.flying);
lifeFiled.setValue(currentData.life);
atlas.getEdit().setText(currentData.sprite);
if(currentData.equipment!=null)

View File

@@ -0,0 +1,19 @@
package forge.adventure.editor;
import javax.swing.*;
public class FloatSpinner extends JSpinner{
public FloatSpinner()
{
this( 0.f, 1f, 0.1f);
}
public FloatSpinner(float min,float max,float stepSize)
{
super(new SpinnerNumberModel(new Float(0.0f), new Float(min), new Float (max), new Float(stepSize)));
}
public float floatValue()
{
return ((Float)getValue()).floatValue();
}
}

View File

@@ -0,0 +1,63 @@
package forge.adventure.editor;
import javax.swing.*;
import java.awt.*;
public class FormPanel extends JPanel {
int row=0;
static final int MAXIMUM_LINES=300;
public FormPanel()
{
setLayout(new GridBagLayout()) ;
GridBagConstraints constraint=new GridBagConstraints();
constraint.weightx = 1.0;
constraint.weighty = 1.0;
constraint.gridy=MAXIMUM_LINES;
constraint.gridx=0;
constraint.gridwidth=2;
add(Box.createVerticalGlue(),constraint);
row++;
}
public void add(JComponent name,JComponent element)
{
GridBagConstraints constraint=new GridBagConstraints();
constraint.ipadx = 5;
constraint.ipady = 5;
constraint.weightx = 1.0;
constraint.weighty = 0.0;
constraint.gridy=row;
constraint.gridx=0;
constraint.anchor=GridBagConstraints.NORTHWEST;
add(name,constraint);
constraint.gridy=row;
constraint.gridx=1;
constraint.fill=GridBagConstraints.HORIZONTAL;
constraint.anchor=GridBagConstraints.NORTHEAST;
add(element,constraint);
row++;
}
public void add(String name,JComponent element)
{
add(new JLabel(name),element);
}
public void add(JComponent element)
{
GridBagConstraints constraint=new GridBagConstraints();
constraint.ipadx = 5;
constraint.ipady = 5;
constraint.weightx = 1.0;
constraint.weighty = 0.0;
constraint.gridy=row;
constraint.gridx=0;
constraint.gridwidth=2;
constraint.fill=GridBagConstraints.HORIZONTAL;
constraint.anchor=GridBagConstraints.NORTHEAST;
add(element,constraint);
row++;
}
}

View File

@@ -0,0 +1,20 @@
package forge.adventure.editor;
import javax.swing.*;
public class IntSpinner extends JSpinner {
public IntSpinner()
{
this( 0, 100, 1);
}
public IntSpinner(int min,int max,int stepSize)
{
super(new SpinnerNumberModel(new Integer(0), new Integer(min), new Integer (max), new Integer(stepSize)));
}
public int intValue()
{
return ((Integer)getValue()).intValue();
}
}

View File

@@ -10,8 +10,6 @@ import java.awt.*;
*/
public class ItemEdit extends JComponent {
ItemData currentData;
JTextField nameField=new JTextField();
JTextField equipmentSlot=new JTextField();
JTextField iconName=new JTextField();
@@ -26,19 +24,19 @@ public class ItemEdit extends JComponent {
{
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
JPanel parameters=new JPanel();
FormPanel parameters=new FormPanel();
parameters.setBorder(BorderFactory.createTitledBorder("Parameter"));
parameters.setLayout(new GridLayout(6,2)) ;
parameters.add(new JLabel("Name:")); parameters.add(nameField);
parameters.add(new JLabel("equipmentSlot:")); parameters.add(equipmentSlot);
parameters.add(new JLabel("description:")); parameters.add(description);
parameters.add(new JLabel("iconName")); parameters.add(iconName);
parameters.add(new JLabel("questItem")); parameters.add(questItem);
parameters.add(new JLabel("cost")); parameters.add(cost);
parameters.add("Name:",nameField);
parameters.add("equipmentSlot:",equipmentSlot);
parameters.add("description:",description);
parameters.add("iconName",iconName);
parameters.add("questItem",questItem);
parameters.add("cost",cost);
add(parameters);
add(effect);
add(new Box.Filler(new Dimension(0,0),new Dimension(0,Integer.MAX_VALUE),new Dimension(0,Integer.MAX_VALUE)));
nameField.getDocument().addDocumentListener(new DocumentChangeListener(() -> ItemEdit.this.updateItem()));
equipmentSlot.getDocument().addDocumentListener(new DocumentChangeListener(() -> ItemEdit.this.updateItem()));

View File

@@ -0,0 +1,85 @@
package forge.adventure.editor;
import forge.adventure.data.PointOfInterestData;
import javax.swing.*;
public class PointOfInterestEdit extends JComponent {
PointOfInterestData currentData;
JTextField name = new JTextField();
JTextField type = new JTextField();
JSpinner count = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1));
FilePicker spriteAtlas = new FilePicker(new String[]{"atlas"});
JTextField sprite = new JTextField();
FilePicker map = new FilePicker(new String[]{"tmx"});
JSpinner radiusFactor= new JSpinner(new SpinnerNumberModel(0.0f, 0.0f, 2.0f, 0.1f));
private boolean updating=false;
public PointOfInterestEdit()
{
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
FormPanel parameters=new FormPanel();
parameters.setBorder(BorderFactory.createTitledBorder("Parameter"));
parameters.add("Name:",name);
parameters.add("Type:",type);
parameters.add("Count:",count);
parameters.add("Sprite atlas:",spriteAtlas);
parameters.add("Sprite:",sprite);
parameters.add("Map:",map);
parameters.add("Radius factor:",radiusFactor);
add(parameters);
name.getDocument().addDocumentListener(new DocumentChangeListener(() -> PointOfInterestEdit.this.updateItem()));
type.getDocument().addDocumentListener(new DocumentChangeListener(() -> PointOfInterestEdit.this.updateItem()));
count.addChangeListener(e -> PointOfInterestEdit.this.updateItem());
spriteAtlas.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> PointOfInterestEdit.this.updateItem()));
sprite.getDocument().addDocumentListener(new DocumentChangeListener(() -> PointOfInterestEdit.this.updateItem()));
map.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> PointOfInterestEdit.this.updateItem()));
radiusFactor.addChangeListener(e -> PointOfInterestEdit.this.updateItem());
refresh();
}
private void updateItem() {
if(currentData==null||updating)
return;
currentData.name=name.getText();
currentData.type= type.getText();
currentData.count= ((Integer) count.getValue()).intValue();
currentData.spriteAtlas=spriteAtlas.getEdit().getText();
currentData.sprite=sprite.getText();
currentData.map=map.getEdit().getText();
currentData.radiusFactor=((Float) radiusFactor.getValue()).floatValue();
}
public void setCurrent(PointOfInterestData data)
{
currentData=data;
refresh();
}
private void refresh() {
setEnabled(currentData!=null);
if(currentData==null)
{
return;
}
updating=true;
name.setText(currentData.name);
type.setText(currentData.type);
count.setValue(currentData.count);
spriteAtlas.getEdit().setText(currentData.spriteAtlas);
sprite.setText(currentData.sprite);
map.getEdit().setText(currentData.map);
radiusFactor.setValue(currentData.radiusFactor);
updating=false;
}
}

View File

@@ -1,6 +1,131 @@
package forge.adventure.editor;
import java.awt.*;
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.PointOfInterestData;
import forge.adventure.util.Config;
import forge.adventure.util.Paths;
public class PointOfInterestEditor extends Component {
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.util.HashMap;
public class PointOfInterestEditor extends JComponent {
DefaultListModel<PointOfInterestData> model = new DefaultListModel<>();
JList<PointOfInterestData> list = new JList<>(model);
JToolBar toolBar = new JToolBar("toolbar");
PointOfInterestEdit edit=new PointOfInterestEdit();
static HashMap<String,SwingAtlas> atlas=new HashMap<>();
public class PointOfInterestRenderer 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 PointOfInterestData))
return label;
PointOfInterestData poi=(PointOfInterestData) value;
// Get the renderer component from parent class
label.setText(poi.name);
if(!atlas.containsKey(poi.spriteAtlas))
atlas.put(poi.spriteAtlas,new SwingAtlas(Config.instance().getFile(poi.spriteAtlas)));
SwingAtlas poiAtlas = atlas.get(poi.spriteAtlas);
if(poiAtlas.has(poi.sprite))
label.setIcon(poiAtlas.get(poi.sprite));
else
{
ImageIcon img=poiAtlas.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 PointOfInterestEditor()
{
list.setCellRenderer(new PointOfInterestEditor.PointOfInterestRenderer());
list.addListSelectionListener(e -> PointOfInterestEditor.this.updateEdit());
addButton("add", e -> PointOfInterestEditor.this.addItem());
addButton("remove", e -> PointOfInterestEditor.this.remove());
addButton("copy", e -> PointOfInterestEditor.this.copy());
addButton("load", e -> PointOfInterestEditor.this.load());
addButton("save", e -> PointOfInterestEditor.this.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;
PointOfInterestData data=new PointOfInterestData(model.get(selected));
model.add(model.size(),data);
}
private void updateEdit() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
edit.setCurrent(model.get(selected));
}
void save()
{
Array<PointOfInterestData> 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.POINTS_OF_INTEREST);
handle.writeString(json.prettyPrint(json.toJson(allEnemies,Array.class, PointOfInterestData.class)),false);
}
void load()
{
model.clear();
Array<PointOfInterestData> allEnemies=new Array<>();
Json json = new Json();
FileHandle handle = Config.instance().getFile(Paths.POINTS_OF_INTEREST);
if (handle.exists())
{
Array readEnemies=json.fromJson(Array.class, PointOfInterestData.class, handle);
allEnemies = readEnemies;
}
for (int i=0;i<allEnemies.size;i++) {
model.add(i,allEnemies.get(i));
}
}
void addItem()
{
PointOfInterestData data=new PointOfInterestData();
data.name="PoI "+model.getSize();
model.add(model.size(),data);
}
void remove()
{
int selected=list.getSelectedIndex();
if(selected<0)
return;
model.remove(selected);
}
}

View File

@@ -7,15 +7,12 @@ import forge.game.keyword.Keyword;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class RewardEdit extends JComponent {
public class RewardEdit extends FormPanel {
RewardData currentData;
JComboBox typeField =new JComboBox(new String[] { "card", "gold", "life", "deckCard", "item"});
@@ -38,122 +35,41 @@ public class RewardEdit extends JComponent {
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);
add("Type:",typeField);
add("probability:",probability);
add("count:",count);
add("addMaxCount:",addMaxCount);
add("cardName:",cardName);
add("itemName:",itemName);
add("editions:",editions);
add("colors:",colors);
add("rarity:",rarity);
add("subTypes:",subTypes);
add("cardTypes:",cardTypes);
add("superTypes:",superTypes);
add("manaCosts:",manaCosts);
add("keyWords:",keyWords);
add("colorType:",colorType);
add("cardText:",cardText);
typeField.addActionListener((new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
RewardEdit.this.updateReward();
}
}));
probability.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
RewardEdit.this.updateReward();
}
});
count.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
RewardEdit.this.updateReward();
}
});
addMaxCount.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
RewardEdit.this.updateReward();
}
});
cardName.getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
itemName.getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
editions.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
colors.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
rarity.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
subTypes.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
cardTypes.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
superTypes.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
manaCosts.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
keyWords.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
colorType.addActionListener((new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
RewardEdit.this.updateReward();
}
}));
cardText.getDocument().addDocumentListener(new DocumentChangeListener(new Runnable() {
@Override
public void run() {
RewardEdit.this.updateReward();
}
}));
typeField.addActionListener((e -> RewardEdit.this.updateReward()));
probability.addChangeListener(e -> RewardEdit.this.updateReward());
count.addChangeListener(e -> RewardEdit.this.updateReward());
addMaxCount.addChangeListener(e -> RewardEdit.this.updateReward());
cardName.getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
itemName.getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
editions.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
colors.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
rarity.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
subTypes.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
cardTypes.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
superTypes.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
manaCosts.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
keyWords.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
colorType.addActionListener((e -> RewardEdit.this.updateReward()));
cardText.getDocument().addDocumentListener(new DocumentChangeListener(() -> RewardEdit.this.updateReward()));
}

View File

@@ -5,10 +5,7 @@ import forge.adventure.data.RewardData;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
@@ -59,30 +56,10 @@ public class RewardsEditor extends JComponent{
{
list.setCellRenderer(new RewardDataRenderer());
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
RewardsEditor.this.updateEdit();
}
});
addButton("add", new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
RewardsEditor.this.addReward();
}
});
addButton("remove", new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
RewardsEditor.this.remove();
}
});
addButton("copy", new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
RewardsEditor.this.copy();
}
});
list.addListSelectionListener(e -> RewardsEditor.this.updateEdit());
addButton("add", e -> RewardsEditor.this.addReward());
addButton("remove", e -> RewardsEditor.this.remove());
addButton("copy", e -> RewardsEditor.this.copy());
BorderLayout layout=new BorderLayout();
setLayout(layout);
add(list, BorderLayout.LINE_START);

View File

@@ -0,0 +1,222 @@
package forge.adventure.editor;
import com.badlogic.gdx.graphics.Color;
import forge.adventure.data.BiomeData;
import forge.adventure.data.BiomeStructureData;
import forge.adventure.util.Config;
import forge.adventure.world.BiomeStructure;
import forge.adventure.world.ColorMap;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
/**
* Editor class to edit configuration, maybe moved or removed
*/
public class StructureEditor extends JComponent{
DefaultListModel<BiomeStructureData> model = new DefaultListModel<>();
JList<BiomeStructureData> list = new JList<>(model);
JToolBar toolBar = new JToolBar("toolbar");
BiomeStructureEdit edit=new BiomeStructureEdit();
BiomeData currentData;
public class StructureDataRenderer 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 BiomeStructureData))
return label;
BiomeStructureData structureData=(BiomeStructureData) value;
label.setText("Structure");
label.setIcon(new ImageIcon(Config.instance().getFilePath(structureData.sourcePath)));
return label;
}
}
public void addButton(String name, ActionListener action)
{
JButton newButton=new JButton(name);
newButton.addActionListener(action);
toolBar.add(newButton);
}
public StructureEditor()
{
list.setCellRenderer(new StructureDataRenderer());
list.addListSelectionListener(e -> StructureEditor.this.updateEdit());
addButton("add", e -> StructureEditor.this.addStructure());
addButton("remove", e -> StructureEditor.this.remove());
addButton("copy", e -> StructureEditor.this.copy());
addButton("test", e -> StructureEditor.this.test());
BorderLayout layout=new BorderLayout();
setLayout(layout);
add(list, BorderLayout.WEST);
add(toolBar, BorderLayout.NORTH);
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 test() {
if (list.isSelectionEmpty())
return;
long start = System.currentTimeMillis();
BiomeStructureData data = model.get(list.getSelectedIndex());
try
{
BiomeStructure struct = new BiomeStructure(data, System.currentTimeMillis(),
(int) (currentData.width * EditorMainWindow.worldEditor.width.intValue() ),
(int) (currentData.width * EditorMainWindow.worldEditor.height.intValue()));
BufferedImage sourceImage= null;
try {
sourceImage = ImageIO.read(new File(struct.sourceImagePath()));
ColorMap sourceColorMap=new ColorMap(sourceImage.getWidth(),sourceImage.getHeight());
for(int y=0;y<sourceColorMap.getHeight();y++)
for(int x=0;x<sourceColorMap.getWidth();x++)
{
Color c =new Color();
Color.argb8888ToColor(c,sourceImage.getRGB(x,y));
sourceColorMap.setColor(x,y,c);
}
BufferedImage maskImage= ImageIO.read(new File(struct.maskImagePath()));
ColorMap maskColorMap=new ColorMap(maskImage.getWidth(),maskImage.getHeight());
for(int y=0;y<maskColorMap.getHeight();y++)
for(int x=0;x<maskColorMap.getWidth();x++)
{
Color c =new Color();
Color.argb8888ToColor(c,maskImage.getRGB(x,y));
maskColorMap.setColor(x,y,c);
}
struct.initialize(sourceColorMap,maskColorMap);
} catch (IOException e) {
throw new RuntimeException(e);
}
float calcTime=(System.currentTimeMillis() - start)/1000f;
JLabel label = new JLabel();
ColorMap colorMap=struct.image;
BufferedImage image = new BufferedImage(colorMap.getWidth(),colorMap.getHeight(),BufferedImage.TYPE_INT_ARGB);
for(int y=0;y<colorMap.getHeight();y++)
for(int x=0;x<colorMap.getWidth();x++)
image.setRGB(x,y,Color.argb8888(colorMap.getColor(x,y)));
if (image.getWidth() < 640 | image.getHeight() < 640) {
if (image.getHeight() > image.getWidth()) {
BufferedImage nimage = new BufferedImage(640, 640 * (image.getWidth() / image.getHeight()), BufferedImage.TYPE_INT_ARGB);
AffineTransform at = new AffineTransform();
at.scale(640 / image.getHeight(), 640 / image.getHeight());
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
image = scaleOp.filter(image, nimage);
} else {
BufferedImage nimage = new BufferedImage(640 * (image.getHeight() / image.getWidth()), 640, BufferedImage.TYPE_INT_ARGB);
AffineTransform at = new AffineTransform();
at.scale(640 / image.getWidth(), 640 / image.getWidth());
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
image = scaleOp.filter(image, nimage);
}
}
label.setIcon(new ImageIcon(image));
label.setSize(640, 640);
JOptionPane.showMessageDialog(this, label,"Calculating took "+ calcTime+" seconds",JOptionPane.PLAIN_MESSAGE);
}
catch (Exception e)
{
JOptionPane.showMessageDialog(this, "WaveFunctionCollapse was not successful","can not calculate function "+e.getMessage(),JOptionPane.ERROR_MESSAGE);
}
}
private void copy() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
BiomeStructureData data=new BiomeStructureData(model.get(selected));
model.add(model.size(),data);
}
private void updateEdit() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
edit.setCurrentStructure(model.get(selected),currentData);
}
void addStructure()
{
BiomeStructureData data=new BiomeStructureData();
model.add(model.size(),data);
}
void remove()
{
int selected=list.getSelectedIndex();
if(selected<0)
return;
model.remove(selected);
}
public void setStructures(BiomeData data) {
currentData=data;
model.clear();
if(data==null||data.structures==null)
{
edit.setCurrentStructure(null,null);
return;
}
for (int i=0;i<data.structures.length;i++) {
model.add(i,data.structures[i]);
}
list.setSelectedIndex(0);
}
public BiomeStructureData[] getBiomeStructureData() {
BiomeStructureData[] rewards= new BiomeStructureData[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

@@ -19,13 +19,15 @@ import static java.awt.Image.SCALE_FAST;
*/
public class SwingAtlas {
int imageSize=32;
HashMap<String, ArrayList<ImageIcon>> images=new HashMap<>();
public HashMap<String, ArrayList<ImageIcon>> getImages()
{
return images;
}
public SwingAtlas(FileHandle path)
public SwingAtlas(FileHandle path,int imageSize)
{
this.imageSize=imageSize;
if(!path.exists()||!path.toString().endsWith(".atlas"))
return;
TextureAtlas.TextureAtlasData data=new TextureAtlas.TextureAtlasData(path,path.parent(),false);
@@ -37,20 +39,41 @@ public class SwingAtlas {
images.put(name,new ArrayList<>());
}
ArrayList<ImageIcon> imageList=images.get(name);
try {
try
{
imageList.add(spriteToImage(region));
} catch (IOException e) {
}
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 SwingAtlas(FileHandle path)
{
this(path,32);
}
private ImageIcon spriteToImage(TextureAtlas.TextureAtlasData.Region sprite) throws IOException {
try
{
BufferedImage img = ImageIO.read(sprite.page.textureFile.file());
if(sprite.width== sprite.height)
return new ImageIcon(img.getSubimage(sprite.left,sprite.top, sprite.width, sprite.height).getScaledInstance(imageSize,imageSize,SCALE_FAST));
if(sprite.width>sprite.height)
return new ImageIcon(img.getSubimage(sprite.left,sprite.top, sprite.width, sprite.height).getScaledInstance(imageSize, (int) (imageSize*(sprite.height/(float)sprite.width)),SCALE_FAST));
return new ImageIcon(img.getSubimage(sprite.left,sprite.top, sprite.width, sprite.height).getScaledInstance((int) (imageSize*(sprite.width/(float)sprite.height)),imageSize,SCALE_FAST));
}
catch (IOException e)
{
return null;
}
}
public ImageIcon get(String name) {
if(images.get(name).size()==0)
return null;
return images.get(name).get(0);
}

View File

@@ -13,11 +13,12 @@ import java.util.Map;
* Editor class to edit configuration, maybe moved or removed
*/
public class SwingAtlasPreview extends Box {
int imageSize=32;
private String sprite="";
private String spriteName="";
Timer timer;
public SwingAtlasPreview() {
super(BoxLayout.Y_AXIS);
timer = new Timer(200, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -28,25 +29,50 @@ public class SwingAtlasPreview extends Box {
}
});
}
public SwingAtlasPreview(int size) {
this();
imageSize=size;
}
int counter=0;
List<Pair<JLabel,ArrayList<ImageIcon>>> labels=new ArrayList<>();
public void setSpritePath(String sprite) {
if(this.sprite==null||this.sprite.equals(sprite))
setSpritePath(sprite,null);
}
public void setSpritePath(String sprite,String name) {
if(this.sprite==null||sprite==null||(this.sprite.equals(sprite)&&(spriteName!=null&&name!=null&&spriteName.equals(name))))
return;
removeAll();
counter=0;
labels.clear();
this.sprite=sprite;
SwingAtlas atlas=new SwingAtlas(Config.instance().getFile(sprite));
this.spriteName=name;
SwingAtlas atlas=new SwingAtlas(Config.instance().getFile(sprite),imageSize);
int maxCount=0;
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()));
if(name==null||element.getKey().equals(name))
{
JLabel image=new JLabel(element.getValue().get(0));
if(maxCount<element.getValue().size())
maxCount=element.getValue().size();
add(new JLabel(element.getKey()));
add(image);
labels.add(Pair.of(image, element.getValue()));
}
}
timer.restart();
if(maxCount<=1)
{
timer.stop();
}
else
{
timer.restart();
}
doLayout();
revalidate();
update(getGraphics());
repaint();
}
}

View File

@@ -0,0 +1,132 @@
package forge.adventure.editor;
import forge.adventure.data.BiomeData;
import forge.adventure.data.BiomeTerrainData;
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 TerrainsEditor extends JComponent{
DefaultListModel<BiomeTerrainData> model = new DefaultListModel<>();
JList<BiomeTerrainData> list = new JList<>(model);
JToolBar toolBar = new JToolBar("toolbar");
BiomeTerrainEdit edit=new BiomeTerrainEdit();
BiomeData currentData;
public class TerrainDataRenderer 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 BiomeTerrainData))
return label;
BiomeTerrainData terrainData=(BiomeTerrainData) value;
StringBuilder builder=new StringBuilder();
builder.append("Terrain");
builder.append(" ");
builder.append(terrainData.spriteName);
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 TerrainsEditor()
{
list.setCellRenderer(new TerrainDataRenderer());
list.addListSelectionListener(e -> TerrainsEditor.this.updateEdit());
addButton("add", e -> TerrainsEditor.this.addTerrain());
addButton("remove", e -> TerrainsEditor.this.remove());
addButton("copy", e -> TerrainsEditor.this.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;
BiomeTerrainData data=new BiomeTerrainData(model.get(selected));
model.add(model.size(),data);
}
private void updateEdit() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
edit.setCurrentTerrain(model.get(selected),currentData);
}
void addTerrain()
{
BiomeTerrainData data=new BiomeTerrainData();
model.add(model.size(),data);
}
void remove()
{
int selected=list.getSelectedIndex();
if(selected<0)
return;
model.remove(selected);
}
public void setTerrains(BiomeData data) {
currentData=data;
model.clear();
if(data==null||data.terrain==null)
return;
for (int i=0;i<data.terrain.length;i++) {
model.add(i,data.terrain[i]);
}
list.setSelectedIndex(0);
}
public BiomeTerrainData[] getBiomeTerrainData() {
BiomeTerrainData[] rewards= new BiomeTerrainData[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

@@ -3,10 +3,12 @@ package forge.adventure.editor;
import forge.adventure.util.Config;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* Editor class to edit configuration, maybe moved or removed
@@ -26,6 +28,7 @@ public class TextListEdit extends Box {
});
add(edit);
edit.setPreferredSize(new Dimension(400,edit.getPreferredSize().height));
//add(findButton);
elements= new JComboBox(possibleElements);
add(elements);
@@ -59,6 +62,12 @@ public class TextListEdit extends Box {
}
}
public void setText(List<String> itemNames) {
if(itemNames==null)
edit.setText("");
else
edit.setText(String.join(";",itemNames));
}
public void setText(String[] itemName) {
if(itemName==null)
edit.setText("");
@@ -77,7 +86,7 @@ public class TextListEdit extends Box {
{
values.append(intValues[i]);
if(intValues.length>i+2)
values.append(";");
values.append("\n");
}
edit.setText(values.toString());
}

View File

@@ -1,6 +1,226 @@
package forge.adventure.editor;
import java.awt.*;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonWriter;
import forge.adventure.data.BiomeData;
import forge.adventure.data.WorldData;
import forge.adventure.util.Config;
import forge.adventure.util.Paths;
public class WorldEditor extends Component {
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
public class WorldEditor extends JComponent {
WorldData currentData;
IntSpinner width= new IntSpinner( 0, 100000, 1);
IntSpinner height= new IntSpinner( 0, 100000, 1);
FloatSpinner playerStartPosX= new FloatSpinner( 0, 1, .1f);
FloatSpinner playerStartPosY= new FloatSpinner(0, 1, .1f);
FloatSpinner noiseZoomBiome= new FloatSpinner( 0, 1000f, 1f);
IntSpinner tileSize= new IntSpinner( 0, 100000, 1);
JTextField biomesSprites = new JTextField();
FloatSpinner maxRoadDistance = new FloatSpinner( 0, 100000f, 1f);
TextListEdit biomesNames = new TextListEdit();
DefaultListModel<BiomeData> model = new DefaultListModel<>();
JList<BiomeData> list = new JList<>(model);
BiomeEdit edit=new BiomeEdit();
JTabbedPane tabs =new JTabbedPane();
static HashMap<String,SwingAtlas> atlas=new HashMap<>();
public class BiomeDataRenderer 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 BiomeData))
return label;
BiomeData biome=(BiomeData) value;
// Get the renderer component from parent class
label.setText(biome.name);
if(!atlas.containsKey(biome.tilesetAtlas))
atlas.put(biome.tilesetAtlas,new SwingAtlas(Config.instance().getFile(biome.tilesetAtlas)));
SwingAtlas poiAtlas = atlas.get(biome.tilesetAtlas);
if(poiAtlas.has(biome.tilesetName))
label.setIcon(poiAtlas.get(biome.tilesetName));
else
{
ImageIcon img=poiAtlas.getAny();
if(img!=null)
label.setIcon(img);
}
return label;
}
}
/**
*
*/
private void updateBiome() {
int selected=list.getSelectedIndex();
if(selected<0)
return;
edit.setCurrentBiome(model.get(selected));
}
public WorldEditor() {
list.setCellRenderer(new BiomeDataRenderer());
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
WorldEditor.this.updateBiome();
}
});
BorderLayout layout = new BorderLayout();
setLayout(layout);
add(tabs);
JSplitPane biomeData=new JSplitPane();
tabs.addTab("BiomeData", biomeData);
FormPanel worldPanel=new FormPanel();
worldPanel.add("width:",width);
worldPanel.add("height:",height);
worldPanel.add("playerStartPosX:",playerStartPosX);
worldPanel.add("playerStartPosY:",playerStartPosY);
worldPanel.add("noiseZoomBiome:",noiseZoomBiome);
worldPanel.add("tileSize:",tileSize);
worldPanel.add("biomesSprites:",biomesSprites);
worldPanel.add("maxRoadDistance:",maxRoadDistance);
worldPanel.add("biomesNames:",biomesNames);
tabs.addTab("WorldData", worldPanel);
JScrollPane pane = new JScrollPane(edit);
biomeData.setLeftComponent(list); biomeData.setRightComponent(pane);
load();
JToolBar toolBar = new JToolBar("toolbar");
add(toolBar, BorderLayout.PAGE_START);
JButton newButton=new JButton("save");
newButton.addActionListener(e -> WorldEditor.this.save());
toolBar.add(newButton);
newButton=new JButton("save selected biome");
newButton.addActionListener(e -> WorldEditor.this.saveBiome());
toolBar.add(newButton);
newButton=new JButton("load");
newButton.addActionListener(e -> WorldEditor.this.load());
toolBar.add(newButton);
toolBar.addSeparator();
newButton=new JButton("test map");
newButton.addActionListener(e -> WorldEditor.this.test());
toolBar.add(newButton);
}
private void test() {
String javaHome = System.getProperty("java.home");
String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
String classpath = System.getProperty("java.class.path");
String className = forge.adventure.Main.class.getName();
ArrayList<String> command = new ArrayList<>();
command.add(javaBin);
command.add("-cp");
command.add(classpath);
command.add(className);
command.add("testMap");
ProcessBuilder build= new ProcessBuilder(command);
build .redirectInput(ProcessBuilder.Redirect.INHERIT)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT);
try {
Process process= build.start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
void saveBiome()
{
edit.updateTerrain();
Json json = new Json(JsonWriter.OutputType.json);
FileHandle handle = Config.instance().getFile(currentData.biomesNames[list.getSelectedIndex()]);
handle.writeString(json.prettyPrint(json.toJson(edit.currentData, BiomeData.class)),false);
}
void save()
{
currentData.width=width.intValue();
currentData.height=height.intValue();
currentData.playerStartPosX=playerStartPosX.floatValue();
currentData.playerStartPosY=playerStartPosY.floatValue();
currentData.noiseZoomBiome=noiseZoomBiome.floatValue();
currentData.tileSize=tileSize.intValue();
currentData.biomesSprites=biomesSprites.getText();
currentData.maxRoadDistance=maxRoadDistance.floatValue();
currentData.biomesNames= (biomesNames.getList());
Json json = new Json(JsonWriter.OutputType.json);
FileHandle handle = Config.instance().getFile(Paths.WORLD);
handle.writeString(json.prettyPrint(json.toJson(currentData, WorldData.class)),false);
}
void load()
{
model.clear();
Json json = new Json();
FileHandle handle = Config.instance().getFile(Paths.WORLD);
if (handle.exists())
{
currentData=json.fromJson(WorldData.class, WorldData.class, handle);
}
update();
}
private void update() {
width.setValue(currentData.width);
height.setValue(currentData.height);
playerStartPosX.setValue(currentData.playerStartPosX);
playerStartPosY.setValue(currentData.playerStartPosY);
noiseZoomBiome.setValue(currentData.noiseZoomBiome);
tileSize.setValue(currentData.tileSize);
biomesSprites.setText(currentData.biomesSprites);
maxRoadDistance.setValue(currentData.maxRoadDistance);
biomesNames.setText(currentData.biomesNames);
for(String path:currentData.biomesNames)
{
Json json = new Json();
FileHandle handle = Config.instance().getFile(path);
if (handle.exists())
{
BiomeData data=json.fromJson(BiomeData.class, BiomeData.class, handle);
model.addElement(data);
}
}
}
}

View File

@@ -778,9 +778,12 @@ public class ComputerUtilCost {
// Check if the AI intends to play the card and if it can pay for it with the mana it has
boolean willPlay = ComputerUtil.hasReasonToPlayCardThisTurn(payer, c);
boolean canPay = c.getManaCost().canBePaidWithAvailable(ColorSet.fromNames(getAvailableManaColors(payer, source)).getColor());
return canPay && willPlay;
if (canPay && willPlay) {
return true;
}
}
}
return false;
}
}
}

View File

@@ -65,10 +65,6 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect {
source.addRemembered(c);
}
if ((power != null) || (toughness != null)) {
c.addNewPT(power, toughness, timestamp, 0);
}
if (!addType.isEmpty() || !removeType.isEmpty() || addAllCreatureTypes || removeSuperTypes
|| removeCardTypes || removeSubTypes || removeLandTypes || removeCreatureTypes || removeArtifactTypes || removeEnchantmentTypes) {
c.addChangedCardTypes(addType, removeType, addAllCreatureTypes, removeSuperTypes, removeCardTypes, removeSubTypes,
@@ -77,6 +73,11 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect {
c.addChangedCardKeywords(keywords, removeKeywords, removeAll, timestamp, 0);
// do this after changing types in case it wasn't a creature before
if (power != null || toughness != null) {
c.addNewPT(power, toughness, timestamp, 0);
}
if (sa.hasParam("CantHaveKeyword")) {
c.addCantHaveKeyword(timestamp, Keyword.setValueOf(sa.getParam("CantHaveKeyword")));
}

View File

@@ -1131,7 +1131,7 @@ public class CardFactoryUtil {
SpellAbility loseLifeSA = AbilityFactory.getAbility(loseLifeStr, card);
AbilitySub gainLifeSA = (AbilitySub) AbilityFactory.getAbility(gainLifeStr, card);
gainLifeSA.setSVar("AFLifeLost", "Number$0");
loseLifeSA.setSVar("AFLifeLost", "Number$0");
loseLifeSA.setSubAbility(gainLifeSA);
loseLifeSA.setIntrinsic(intrinsic);

View File

@@ -1247,12 +1247,17 @@ public class CardView extends GameEntityView {
return get(TrackableProperty.Power);
}
void updatePower(Card c) {
if (c.getCurrentState().getView() == this || c.getAlternateState() == null) {
set(TrackableProperty.Power, c.getNetPower());
int num;
if (getType().hasSubtype("Vehicle") && !isCreature()) {
// use printed value so user can still see it
num = c.getCurrentPower();
} else {
num = c.getNetPower();
}
else {
set(TrackableProperty.Power, c.getNetPower() - c.getBasePower() + c.getAlternateState().getBasePower());
if (c.getCurrentState().getView() != this && c.getAlternateState() != null) {
num -= c.getBasePower() + c.getAlternateState().getBasePower();
}
set(TrackableProperty.Power, num);
}
void updatePower(CardState c) {
Card card = c.getCard();
@@ -1267,12 +1272,17 @@ public class CardView extends GameEntityView {
return get(TrackableProperty.Toughness);
}
void updateToughness(Card c) {
if (c.getCurrentState().getView() == this || c.getAlternateState() == null) {
set(TrackableProperty.Toughness, c.getNetToughness());
int num;
if (getType().hasSubtype("Vehicle") && !isCreature()) {
// use printed value so user can still see it
num = c.getCurrentToughness();
} else {
num = c.getNetToughness();
}
else {
set(TrackableProperty.Toughness, c.getNetToughness() - c.getBaseToughness() + c.getAlternateState().getBaseToughness());
if (c.getCurrentState().getView() != this && c.getAlternateState() != null) {
num -= c.getBaseToughness() + c.getAlternateState().getBaseToughness();
}
set(TrackableProperty.Toughness, num);
}
void updateToughness(CardState c) {
Card card = c.getCard();

View File

@@ -123,6 +123,7 @@ public class Forge implements ApplicationListener {
private static Cursor cursor0, cursor1, cursor2, cursorA0, cursorA1, cursorA2;
public static boolean forcedEnglishonCJKMissing = false;
public static boolean adventureLoaded = false;
public static boolean createNewAdventureMap = false;
private static Localizer localizer;
public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0, boolean value, boolean androidOrientation, int totalRAM, boolean isTablet, int AndroidAPI, String AndroidRelease, String deviceName) {
@@ -328,6 +329,9 @@ public class Forge implements ApplicationListener {
altZoneTabs = true;
//pixl cursor for adventure
setCursor(null, "0");
loadAdventureResources(true);
}
private static void loadAdventureResources(boolean startScene) {
try {
if(!adventureLoaded)
{
@@ -336,7 +340,8 @@ public class Forge implements ApplicationListener {
}
adventureLoaded=true;
}
switchScene(SceneType.StartScene.instance);
if (startScene)
switchScene(SceneType.StartScene.instance);
} catch (Exception e) {
e.printStackTrace();
}
@@ -362,19 +367,28 @@ public class Forge implements ApplicationListener {
//load Drafts
preloadBoosterDrafts();
FThreads.invokeInEdtLater(() -> {
if (selector.equals("Adventure")) {
//preload adventure resources to speedup startup if selector is adventure. Needs in edt when setting up worldstage
loadAdventureResources(false);
}
//selection transition
setTransitionScreen(new TransitionScreen(() -> {
if (selector.equals("Classic")) {
openHomeDefault();
clearSplashScreen();
} else if (selector.equals("Adventure")) {
if (createNewAdventureMap) {
openAdventure();
clearSplashScreen();
} else if (splashScreen != null) {
splashScreen.setShowModeSelector(true);
} else {//default mode in case splashscreen is null at some point as seen on resume..
openHomeDefault();
clearSplashScreen();
} else {
if (selector.equals("Classic")) {
openHomeDefault();
clearSplashScreen();
} else if (selector.equals("Adventure")) {
openAdventure();
clearSplashScreen();
} else if (splashScreen != null) {
splashScreen.setShowModeSelector(true);
} else {//default mode in case splashscreen is null at some point as seen on resume..
openHomeDefault();
clearSplashScreen();
}
}
//start background music
SoundSystem.instance.setBackgroundMusic(MusicPlaylist.MENUS);
@@ -887,6 +901,8 @@ public class Forge implements ApplicationListener {
//check if sentry is enabled, if not it will call the gui interface but here we end the graphics so we only send it via sentry..
if (BugReporter.isSentryEnabled())
BugReporter.reportException(ex);
else
ex.printStackTrace();
}
if (showFPS)
frameRate.render();
@@ -944,10 +960,10 @@ public class Forge implements ApplicationListener {
@Override
public void dispose() {
if (currentScreen != null) {
FOverlay.hideAll();
currentScreen.onClose(null);
currentScreen = null;
}
FOverlay.hideAll();
assets.dispose();
Dscreens.clear();
graphics.dispose();

View File

@@ -1,11 +1,6 @@
package forge.adventure.character;
import com.badlogic.gdx.graphics.g2d.Animation;
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.Rectangle;
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;
@@ -38,7 +33,7 @@ public class CharacterSprite extends MapActor {
@Override
void updateBoundingRect() { //We want a slimmer box for the player entity so it can navigate terrain without getting stuck.
boundingRect = new Rectangle(getX() + 4, getY(), getWidth() - 6, getHeight() * collisionHeight);
boundingRect.set(getX() + 4, getY(), getWidth() - 6, getHeight() * collisionHeight);
}
protected void load(String path) {
@@ -61,8 +56,14 @@ public class CharacterSprite extends MapActor {
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));
if(getWidth()==0.0)//init size onload
{
setWidth(anim.first().getWidth());
setHeight(anim.first().getHeight());
}
}
}
animations.put(stand, dirs);

View File

@@ -4,7 +4,6 @@ import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.utils.Array;
@@ -50,7 +49,7 @@ public class EnemySprite extends CharacterSprite {
@Override
void updateBoundingRect() { //We want enemies to take the full tile.
boundingRect = new Rectangle(getX(), getY(), getWidth(), getHeight());
boundingRect.set(getX(), getY(), getWidth(), getHeight());
}
public void moveTo(Actor other, float delta) {
@@ -182,5 +181,8 @@ public class EnemySprite extends CharacterSprite {
}
}
public float speed() {
return data.speed;
}
}

View File

@@ -14,7 +14,7 @@ public class MapActor extends Actor {
Texture debugTexture;
float collisionHeight=1.0f;
protected float collisionHeight=1.0f;
final int objectId;
public MapActor(int objectId)
{
@@ -35,7 +35,7 @@ public class MapActor extends Actor {
}
return debugTexture;
}
Rectangle boundingRect;
final Rectangle boundingRect=new Rectangle();
boolean isCollidingWithPlayer=false;
protected void onPlayerCollide()
@@ -55,9 +55,8 @@ public class MapActor extends Actor {
}
@Override
protected void positionChanged() {
updateBoundingRect();
super.positionChanged();
updateBoundingRect();
}
@Override
@@ -67,7 +66,7 @@ public class MapActor extends Actor {
}
void updateBoundingRect() {
boundingRect = new Rectangle(getX(), getY(), getWidth(), getHeight()*collisionHeight);
boundingRect.set(getX(), getY(), getWidth(), getHeight()*collisionHeight);
}
public Rectangle boundingRect() {
@@ -106,4 +105,8 @@ public class MapActor extends Actor {
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();
}
public float getCollisionHeight() {
return collisionHeight;
}
}

View File

@@ -1,6 +1,5 @@
package forge.adventure.character;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;
import forge.adventure.data.RewardData;
import forge.adventure.util.JSONStringLoader;
@@ -40,7 +39,7 @@ public class RewardSprite extends CharacterSprite {
@Override
void updateBoundingRect() { //We want rewards to take a full tile.
boundingRect = new Rectangle(getX(), getY(), getWidth(), getHeight());
boundingRect.set(getX(), getY(), getWidth(), getHeight());
}
public Array<Reward> getRewards() { //Get list of rewards.

View File

@@ -6,7 +6,6 @@ import forge.util.MyRandom;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
@@ -15,7 +14,6 @@ import java.util.Random;
* contains the information for the biomes
*/
public class BiomeData implements Serializable {
private final Random rand = MyRandom.getRandom();
public float startPointX;
public float startPointY;
public float noiseWeight;
@@ -27,14 +25,17 @@ public class BiomeData implements Serializable {
public float width;
public float height;
public String color;
public boolean collision;
public boolean invertHeight;
public String[] spriteNames;
public List<String> enemies;
public List<String> pointsOfInterest;
public String[] enemies;
public String[] pointsOfInterest;
public BiomeStructureData[] structures;
private ArrayList<EnemyData> enemyList;
private ArrayList<PointOfInterestData> pointOfInterestList;
private final Random rand = MyRandom.getRandom();
public Color GetColor() {
return Color.valueOf(color);
}
@@ -45,8 +46,13 @@ public class BiomeData implements Serializable {
if (enemies == null)
return enemyList;
for (EnemyData data : new Array.ArrayIterator<>(WorldData.getAllEnemies())) {
if (enemies.contains(data.name)) {
enemyList.add(data);
for (String enemyName:enemies)
{
if(data.name.equals(enemyName))
{
enemyList.add(data);
break;
}
}
}
}
@@ -60,8 +66,13 @@ public class BiomeData implements Serializable {
return pointOfInterestList;
Array<PointOfInterestData> allTowns = PointOfInterestData.getAllPointOfInterest();
for (PointOfInterestData data : new Array.ArrayIterator<>(allTowns)) {
if (pointsOfInterest.contains(data.name)) {
pointOfInterestList.add(data);
for (String poiName:pointsOfInterest)
{
if(data.name.equals(poiName))
{
pointOfInterestList.add(data);
break;
}
}
}
}

View File

@@ -0,0 +1,63 @@
package forge.adventure.data;
public class BiomeStructureData {
static public class BiomeStructureDataMapping
{
public int getColor() {
return ((Integer.parseInt(color,16)<<8)|0xff);
}
public String name;
public String color;
public boolean collision;
public BiomeStructureDataMapping() {
}
public BiomeStructureDataMapping(BiomeStructureDataMapping biomeStructureDataMapping) {
this.name=biomeStructureDataMapping.name;
this.color=biomeStructureDataMapping.color;
this.collision=biomeStructureDataMapping.collision;
}
}
public int N = 3;
public float x;
public float y;
public boolean randomPosition;
public String structureAtlasPath;
public String sourcePath;
public String maskPath;
public boolean periodicInput=true;
public float height;
public float width;
public int ground;
public int symmetry=2;
public boolean periodicOutput=true;
public BiomeStructureDataMapping[] mappingInfo;
public BiomeStructureData( ) {
}
public BiomeStructureData(BiomeStructureData biomeStructureData) {
this.structureAtlasPath=biomeStructureData.structureAtlasPath;
this.sourcePath=biomeStructureData.sourcePath;
this.maskPath=biomeStructureData.maskPath;
this.x=biomeStructureData.x;
this.y=biomeStructureData.y;
this.width=biomeStructureData.width;
this.height=biomeStructureData.height;
this.randomPosition=biomeStructureData.randomPosition;
if(biomeStructureData.mappingInfo!=null)
{
this.mappingInfo=new BiomeStructureDataMapping[ biomeStructureData.mappingInfo.length];
for(int i=0;i<biomeStructureData.mappingInfo.length;i++)
this.mappingInfo[i]=new BiomeStructureDataMapping(biomeStructureData.mappingInfo[i]);
}
else
this.mappingInfo=null;
}
}

View File

@@ -16,4 +16,16 @@ public class BiomeTerrainData {
// factor for the noise resolution
public float resolution;
public BiomeTerrainData()
{
}
public BiomeTerrainData(BiomeTerrainData other)
{
spriteName=other.spriteName;
min=other.min;
max=other.max;
resolution=other.resolution;
}
}

View File

@@ -1,8 +1,6 @@
package forge.adventure.data;
import java.util.List;
/**
* Data class that will be used to read Json configuration files
* BiomeData
@@ -19,6 +17,6 @@ public class ConfigData {
public String[] starterDecks;
public DifficultyData[] difficulties;
public RewardData legalCards;
public List<String> restrictedCards;
public List<String> restrictedEditions;
public String[] restrictedCards;
public String[] restrictedEditions;
}

View File

@@ -15,6 +15,7 @@ public class EnemyData {
public boolean copyPlayerDeck = false;
public String ai;
public boolean boss = false;
public boolean flying = false;
public float spawnRate;
public float difficulty;
public float speed;
@@ -30,6 +31,7 @@ public class EnemyData {
deck = enemyData.deck;
ai = enemyData.ai;
boss = enemyData.boss;
flying = enemyData.flying;
spawnRate = enemyData.spawnRate;
copyPlayerDeck = enemyData.copyPlayerDeck;
difficulty = enemyData.difficulty;

View File

@@ -42,4 +42,18 @@ public class PointOfInterestData {
}
return null;
}
public PointOfInterestData()
{
}
public PointOfInterestData(PointOfInterestData other)
{
name=other.name;
type=other.type;
count=other.count;
spriteAtlas=other.spriteAtlas;
sprite=other.sprite;
map=other.map;
radiusFactor=other.radiusFactor;
}
}

View File

@@ -13,6 +13,7 @@ import forge.item.PaperCard;
import forge.model.FModel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@@ -75,8 +76,8 @@ public class RewardData {
@Override
public boolean apply(PaperCard input){
if(input == null) return false;
if(Config.instance().getConfigData().restrictedEditions.contains(input.getEdition())) return false;
return !Config.instance().getConfigData().restrictedCards.contains(input.getName());
if(Arrays.asList(Config.instance().getConfigData().restrictedEditions).contains(input.getEdition())) return false;
return !Arrays.asList(Config.instance().getConfigData().restrictedCards).contains(input.getName());
}
});
//Filter AI cards for enemies.

View File

@@ -14,4 +14,8 @@ public class SettingData {
public boolean fullScreen;
public String videomode;
public String lastActiveSave;
public Float rewardCardAdj;
public Float cardTooltipAdj;
public Float rewardCardAdjLandscape;
public Float cardTooltipAdjLandscape;
}

View File

@@ -1,6 +1,5 @@
package forge.adventure.data;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.OrderedMap;
/**
@@ -12,5 +11,5 @@ public class UIData {
public int width;
public int height;
public boolean yDown;
public Array<OrderedMap<String,String>> elements;
public OrderedMap<String,String>[] elements;
}

View File

@@ -3,6 +3,7 @@ package forge.adventure.data;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.SerializationException;
import forge.adventure.util.Config;
import forge.adventure.util.Paths;
import forge.adventure.world.BiomeSprites;
@@ -17,19 +18,22 @@ import java.util.List;
*/
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;
public String[] biomesNames;
private BiomeSprites sprites;
private List<BiomeData> biomes;
private static Array<EnemyData> allEnemies;
private static Array<ShopData> shopList;
@@ -77,10 +81,16 @@ public class WorldData implements Serializable {
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)));
try
{
biomes = new ArrayList<BiomeData>();
Json json = new Json();
for (String name : biomesNames) {
biomes.add(json.fromJson(BiomeData.class, Config.instance().getFile(name)));
}
}
catch (SerializationException ex) {
ex.printStackTrace();
}
}
return biomes;

View File

@@ -5,7 +5,10 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Null;
import com.google.common.collect.Lists;
import forge.adventure.data.*;
import forge.adventure.data.DifficultyData;
import forge.adventure.data.EffectData;
import forge.adventure.data.HeroListData;
import forge.adventure.data.ItemData;
import forge.adventure.util.*;
import forge.adventure.world.WorldSave;
import forge.deck.CardPool;
@@ -18,7 +21,10 @@ import forge.util.ItemPool;
import forge.util.MyRandom;
import java.io.Serializable;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Class that represents the player (not the player sprite)

View File

@@ -9,18 +9,10 @@ import forge.adventure.player.AdventurePlayer;
import forge.assets.FImage;
import forge.assets.FSkinFont;
import forge.assets.FSkinImage;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckFormat;
import forge.deck.DeckSection;
import forge.deck.FDeckViewer;
import forge.deck.*;
import forge.item.InventoryItem;
import forge.item.PaperCard;
import forge.itemmanager.CardManager;
import forge.itemmanager.ColumnDef;
import forge.itemmanager.ItemColumn;
import forge.itemmanager.ItemManager;
import forge.itemmanager.ItemManagerConfig;
import forge.itemmanager.*;
import forge.itemmanager.filters.ItemFilter;
import forge.localinstance.properties.ForgePreferences;
import forge.menu.FCheckBoxMenuItem;

View File

@@ -3,12 +3,7 @@ package forge.adventure.scene;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.IntMap;

View File

@@ -4,13 +4,7 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Array;
@@ -228,6 +222,20 @@ public class NewGameScene extends UIScene {
public void enter() {
updateAvatar();
Gdx.input.setInputProcessor(stage); //Start taking input from the ui
if(Forge.createNewAdventureMap)
{
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()],
fantasyMode, easyMode, deck.getText(), 0);
GamePlayerUtil.getGuiPlayer().setName(selectedName.getText());
Forge.switchScene(SceneType.GameScene.instance);
}
}
@Override

View File

@@ -4,11 +4,7 @@ import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import forge.Forge;

View File

@@ -13,10 +13,7 @@ import forge.adventure.character.ShopActor;
import forge.adventure.player.AdventurePlayer;
import forge.adventure.pointofintrest.PointOfInterestChanges;
import forge.adventure.stage.GameHUD;
import forge.adventure.util.CardUtil;
import forge.adventure.util.Current;
import forge.adventure.util.Reward;
import forge.adventure.util.RewardActor;
import forge.adventure.util.*;
import forge.adventure.world.WorldSave;
import forge.assets.ImageCache;
import forge.sound.SoundEffectType;
@@ -222,21 +219,28 @@ public class RewardScene extends UIScene {
float mul = fW/fH < AR ? AR/(fW/fH) : (fW/fH)/AR;
if (fW/fH >= 2f) {//tall display
mul = (fW/fH) - ((fW/fH)/AR);
if ((fW/fH) >= 2.1f && (fW/fH) < 2.3f)
if ((fW/fH) >= 2.1f && (fW/fH) < 2.2f)
mul *= 0.9f;
else if ((fW/fH) > 2.3) //ultrawide 21:9 Galaxy Fold, Huawei X2, Xperia 1
else if ((fW/fH) > 2.2f) //ultrawide 21:9 Galaxy Fold, Huawei X2, Xperia 1
mul *= 0.8f;
}
cardHeight = bestCardHeight * 0.90f ;
if (realX > x || realY > y) {
mul *= Forge.isLandscapeMode() ? 0.95f : 1.05f;
Float custom = Forge.isLandscapeMode() ? Config.instance().getSettingData().rewardCardAdjLandscape : Config.instance().getSettingData().rewardCardAdj;
if (custom != null && custom != 1f) {
mul *= custom;
} else {
//immersive | no navigation and/or showing cutout cam
if (fW/fH > 2.3f)
mul *= Forge.isLandscapeMode() ? 1.1f : 1.6f;
else if (fW/fH > 2f)
mul *= Forge.isLandscapeMode() ? 1.1f : 1.5f;
if (realX > x || realY > y) {
mul *= Forge.isLandscapeMode() ? 0.95f : 1.05f;
} else {
//immersive | no navigation and/or showing cutout cam
if (fW/fH > 2.2f)
mul *= Forge.isLandscapeMode() ? 1.1f : 1.6f;
else if (fW/fH >= 2.1f)
mul *= Forge.isLandscapeMode() ? 1.05f : 1.5f;
else if (fW/fH >= 2f)
mul *= Forge.isLandscapeMode() ? 1f : 1.4f;
}
}
cardWidth = (cardHeight / CARD_WIDTH_TO_HEIGHT)*mul;

View File

@@ -16,8 +16,6 @@ import forge.gui.GuiBase;
import forge.localinstance.properties.ForgePreferences;
import forge.model.FModel;
import java.util.function.Function;
/**
* Scene to handle settings of the base forge and adventure mode
*/
@@ -118,12 +116,7 @@ public class SettingsScene extends UIScene {
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.setTextFieldFilter((textField, c) -> Character.isDigit(c));
text.addListener(change);
addLabel(name);
settingGroup.add(text).align(Align.right);
@@ -145,49 +138,90 @@ public class SettingsScene extends UIScene {
Preference = new ForgePreferences();
}
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;
}
SelectBox plane = Controls.newComboBox(Config.instance().getAllAdventures(), Config.instance().getSettingData().plane, o -> {
Config.instance().getSettingData().plane = (String) o;
Config.instance().saveSettings();
return null;
});
addLabel(Forge.getLocalizer().getMessage("lblWorld"));
settingGroup.add(plane).align(Align.right).pad(2);
if (!GuiBase.isAndroid()) {
SelectBox videomode = Controls.newComboBox(new String[]{"720p", "768p", "900p", "1080p"}, Config.instance().getSettingData().videomode, new Function<Object, Void>() {
@Override
public Void apply(Object o) {
String mode = (String) o;
if (mode == null)
mode = "720p";
Config.instance().getSettingData().videomode = mode;
if (mode.equalsIgnoreCase("768p")) {
Config.instance().getSettingData().width = 1366;
Config.instance().getSettingData().height = 768;
} else if (mode.equalsIgnoreCase("900p")) {
Config.instance().getSettingData().width = 1600;
Config.instance().getSettingData().height = 900;
} else if (mode.equalsIgnoreCase("1080p")) {
Config.instance().getSettingData().width = 1920;
Config.instance().getSettingData().height = 1080;
} else {
Config.instance().getSettingData().width = 1280;
Config.instance().getSettingData().height = 720;
}
Config.instance().saveSettings();
//update preference for classic mode if needed
if (FModel.getPreferences().getPref(ForgePreferences.FPref.UI_VIDEO_MODE) != mode) {
FModel.getPreferences().setPref(ForgePreferences.FPref.UI_VIDEO_MODE, mode);
FModel.getPreferences().save();
}
return null;
SelectBox videomode = Controls.newComboBox(new String[]{"720p", "768p", "900p", "1080p"}, Config.instance().getSettingData().videomode, o -> {
String mode = (String) o;
if (mode == null)
mode = "720p";
Config.instance().getSettingData().videomode = mode;
if (mode.equalsIgnoreCase("768p")) {
Config.instance().getSettingData().width = 1366;
Config.instance().getSettingData().height = 768;
} else if (mode.equalsIgnoreCase("900p")) {
Config.instance().getSettingData().width = 1600;
Config.instance().getSettingData().height = 900;
} else if (mode.equalsIgnoreCase("1080p")) {
Config.instance().getSettingData().width = 1920;
Config.instance().getSettingData().height = 1080;
} else {
Config.instance().getSettingData().width = 1280;
Config.instance().getSettingData().height = 720;
}
Config.instance().saveSettings();
//update preference for classic mode if needed
if (FModel.getPreferences().getPref(ForgePreferences.FPref.UI_VIDEO_MODE) != mode) {
FModel.getPreferences().setPref(ForgePreferences.FPref.UI_VIDEO_MODE, mode);
FModel.getPreferences().save();
}
return null;
});
addLabel(Forge.getLocalizer().getMessage("lblVideoMode"));
settingGroup.add(videomode).align(Align.right).pad(2);
}
if (Forge.isLandscapeMode()) {
//different adjustment to landscape
SelectBox rewardCardAdjLandscape = Controls.newComboBox(new Float[]{0.6f, 0.65f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 1f, 1.05f, 1.1f, 1.15f, 1.2f, 1.25f, 1.3f, 1.35f, 1.4f, 1.45f, 1.5f, 1.55f, 1.6f}, Config.instance().getSettingData().rewardCardAdjLandscape, o -> {
Float val = (Float) o;
if (val == null || val == 0f)
val = 1f;
Config.instance().getSettingData().rewardCardAdjLandscape = val;
Config.instance().saveSettings();
return null;
});
addLabel("Reward/Shop Card Display Ratio");
settingGroup.add(rewardCardAdjLandscape).align(Align.right).pad(2);
SelectBox tooltipAdjLandscape = Controls.newComboBox(new Float[]{0.6f, 0.65f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 1f, 1.05f, 1.1f, 1.15f, 1.2f, 1.25f, 1.3f, 1.35f, 1.4f, 1.45f, 1.5f, 1.55f, 1.6f}, Config.instance().getSettingData().cardTooltipAdjLandscape, o -> {
Float val = (Float) o;
if (val == null || val == 0f)
val = 1f;
Config.instance().getSettingData().cardTooltipAdjLandscape = val;
Config.instance().saveSettings();
return null;
});
addLabel("Reward/Shop Card Tooltip Ratio");
settingGroup.add(tooltipAdjLandscape).align(Align.right).pad(2);
} else {
//portrait adjustment
SelectBox rewardCardAdj = Controls.newComboBox(new Float[]{0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.8f, 1.9f, 2f}, Config.instance().getSettingData().rewardCardAdj, o -> {
Float val = (Float) o;
if (val == null || val == 0f)
val = 1f;
Config.instance().getSettingData().rewardCardAdj = val;
Config.instance().saveSettings();
return null;
});
addLabel("Reward/Shop Card Display Ratio");
settingGroup.add(rewardCardAdj).align(Align.right).pad(2);
SelectBox tooltipAdj = Controls.newComboBox(new Float[]{0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.8f, 1.9f, 2f}, Config.instance().getSettingData().cardTooltipAdj, o -> {
Float val = (Float) o;
if (val == null || val == 0f)
val = 1f;
Config.instance().getSettingData().cardTooltipAdj = val;
Config.instance().saveSettings();
return null;
});
addLabel("Reward/Shop Card Tooltip Ratio");
settingGroup.add(tooltipAdj).align(Align.right).pad(2);
}
if (!GuiBase.isAndroid()) {
addSettingField(Forge.getLocalizer().getMessage("lblFullScreen"), Config.instance().getSettingData().fullScreen, new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
@@ -231,12 +265,7 @@ public class SettingsScene extends UIScene {
settingGroup.row();
back = ui.findActor("return");
back.getLabel().setText(Forge.getLocalizer().getMessage("lblBack"));
ui.onButtonPress("return", new Runnable() {
@Override
public void run() {
SettingsScene.this.back();
}
});
ui.onButtonPress("return", () -> SettingsScene.this.back());
ScrollPane scrollPane = ui.findActor("settings");
scrollPane.setActor(settingGroup);

View File

@@ -3,7 +3,10 @@ package forge.adventure.scene;
import com.badlogic.gdx.graphics.Color;
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.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox;
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 forge.Forge;
@@ -18,10 +21,7 @@ import forge.card.ColorSet;
import forge.item.PaperCard;
import forge.util.MyRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@@ -142,7 +142,7 @@ public class SpellSmithScene extends UIScene {
List<CardEdition> editions = StaticData.instance().getSortedEditions();
editions = editions.stream().filter(input -> {
if(input == null) return false;
return(!Config.instance().getConfigData().restrictedEditions.contains(input.getCode()));
return(!Arrays.asList(Config.instance().getConfigData().restrictedEditions).contains(input.getCode()));
}).collect(Collectors.toList());
editionList = ui.findActor("BSelectPlane");
rewardDummy = ui.findActor("RewardDummy");

View File

@@ -7,9 +7,11 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.utils.Align;
import forge.Forge;
import forge.adventure.stage.GameHUD;
import forge.adventure.stage.GameStage;
import forge.adventure.stage.MapStage;
import forge.adventure.util.Config;
import forge.adventure.util.Controls;
import forge.adventure.util.Current;
import forge.adventure.world.WorldSave;
import forge.screens.TransitionScreen;
@@ -104,6 +106,13 @@ public class StartScene extends UIScene {
}
Gdx.input.setInputProcessor(stage); //Start taking input from the ui
if(Forge.createNewAdventureMap)
{
this.NewGame();
Current.setDebug(true);
GameStage.maximumScrollDistance=4f;
}
}
@Override

View File

@@ -3,19 +3,18 @@ package forge.adventure.stage;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Touchpad;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Scaling;
import com.badlogic.gdx.utils.viewport.ScalingViewport;
import forge.Forge;
@@ -42,7 +41,8 @@ public class GameHUD extends Stage {
private final Image miniMapPlayer;
private final Label lifePoints;
private final Label money;
private final Image miniMap, gamehud, mapborder, avatarborder, blank;
private final Image miniMap,miniMapTooltip, gamehud, mapborder, avatarborder, blank;
private Tooltip<Image> toolTip;
private TextButton deckActor, menuActor, statsActor, inventoryActor;
private UIActor ui;
private Touchpad touchpad;
@@ -63,6 +63,15 @@ public class GameHUD extends Stage {
blank = ui.findActor("blank");
miniMap = ui.findActor("map");
mapborder = ui.findActor("mapborder");
miniMapTooltip=new Image();
miniMapTooltip.setScaling(Scaling.contain);
miniMapTooltip.setSize(miniMap.getWidth()*3,miniMap.getHeight()*3);
miniMapTooltip.setPosition(0,0,Align.topLeft);
ui.addActor(miniMapTooltip);
toolTip=new Tooltip<Image>(miniMapTooltip);
toolTip.setInstant(true);
mapborder.addListener(toolTip);
avatarborder = ui.findActor("avatarborder");
deckActor = ui.findActor("deck");
deckActor.getLabel().setText(Forge.getLocalizer().getMessage("lblDeck"));
@@ -167,6 +176,7 @@ public class GameHUD extends Stage {
return true;
if(Current.isInDebug())
WorldStage.getInstance().GetPlayer().setPosition(x*WorldSave.getCurrentSave().getWorld().getWidthInPixels(),y*WorldSave.getCurrentSave().getWorld().getHeightInPixels());
return true;
}
return super.touchDragged(screenX, screenY, pointer);
@@ -230,12 +240,21 @@ public class GameHUD extends Stage {
}
Texture miniMapTexture;
Texture miniMapToolTipTexture;
Pixmap miniMapToolTipPixmap;
public void enter() {
if(miniMapTexture!=null)
miniMapTexture.dispose();
miniMapTexture=new Texture(WorldSave.getCurrentSave().getWorld().getBiomeImage());
if(miniMapToolTipTexture!=null)
miniMapToolTipTexture.dispose();
if(miniMapToolTipPixmap!=null)
miniMapToolTipPixmap.dispose();
miniMapToolTipPixmap=new Pixmap((int) (miniMap.getWidth()*3), (int) (miniMap.getHeight()*3), Pixmap.Format.RGBA8888);
miniMapToolTipPixmap.drawPixmap(WorldSave.getCurrentSave().getWorld().getBiomeImage(),0,0,WorldSave.getCurrentSave().getWorld().getBiomeImage().getWidth(),WorldSave.getCurrentSave().getWorld().getBiomeImage().getHeight(),0,0,miniMapToolTipPixmap.getWidth(),miniMapToolTipPixmap.getHeight());
miniMapToolTipTexture=new Texture(miniMapToolTipPixmap);
miniMap.setDrawable(new TextureRegionDrawable(miniMapTexture));
miniMapTooltip.setDrawable(new TextureRegionDrawable(miniMapToolTipTexture));
avatar.setDrawable(new TextureRegionDrawable(Current.player().avatar()));
Deck deck = AdventurePlayer.current().getSelectedDeck();
if (deck == null || deck.isEmpty() || deck.getMain().toFlatList().size() < 30) {

View File

@@ -36,6 +36,8 @@ public abstract class GameStage extends Stage {
private float touchY = -1;
private final float timer = 0;
private float animationTimeout = 0;
public static float maximumScrollDistance=1.5f;
public static float minimumScrollDistance=0.3f;
public void startPause(float i) {
startPause(i, null);
@@ -222,10 +224,10 @@ public abstract class GameStage extends Stage {
if (isPaused())
return true;
camera.zoom += (amountY * 0.03);
if (camera.zoom < 0.3f)
camera.zoom = 0.3f;
if (camera.zoom > 1.5f)
camera.zoom = 1.5f;
if (camera.zoom < minimumScrollDistance)
camera.zoom = minimumScrollDistance;
if (camera.zoom > maximumScrollDistance)
camera.zoom = maximumScrollDistance;
return super.scrolled(amountX, amountY);
}

View File

@@ -41,7 +41,6 @@ import forge.screens.TransitionScreen;
import forge.sound.SoundEffectType;
import forge.sound.SoundSystem;
import java.util.HashMap;
import java.util.Map;

View File

@@ -11,11 +11,7 @@ import forge.adventure.character.EnemySprite;
import forge.adventure.data.BiomeData;
import forge.adventure.data.EnemyData;
import forge.adventure.data.WorldData;
import forge.adventure.scene.DuelScene;
import forge.adventure.scene.RewardScene;
import forge.adventure.scene.Scene;
import forge.adventure.scene.SceneType;
import forge.adventure.scene.TileMapScene;
import forge.adventure.scene.*;
import forge.adventure.util.Current;
import forge.adventure.util.SaveFileContent;
import forge.adventure.util.SaveFileData;
@@ -62,6 +58,8 @@ public class WorldStage extends GameStage implements SaveFileContent {
}
final Rectangle tempBoundingRect=new Rectangle();
final Vector2 enemyMoveVector =new Vector2();
@Override
protected void onActing(float delta) {
if (player.isMoving()) {
@@ -79,7 +77,33 @@ public class WorldStage extends GameStage implements SaveFileContent {
continue;
}
EnemySprite mob=pair.getValue();
mob.moveTo(player,delta);
enemyMoveVector.set(player.getX(), player.getY()).sub(mob.pos());
enemyMoveVector.setLength(mob.speed()*delta);
tempBoundingRect.set(mob.getX()+ enemyMoveVector.x,mob.getY()+ enemyMoveVector.y,mob.getWidth(),mob.getHeight()*mob.getCollisionHeight());
if(!mob.getData().flying && WorldSave.getCurrentSave().getWorld().collidingTile(tempBoundingRect))//if direct path is not possible
{
tempBoundingRect.set(mob.getX()+ enemyMoveVector.x,mob.getY(),mob.getWidth(),mob.getHeight());
if(WorldSave.getCurrentSave().getWorld().collidingTile(tempBoundingRect))//if only x path is not possible
{
tempBoundingRect.set(mob.getX(),mob.getY()+ enemyMoveVector.y,mob.getWidth(),mob.getHeight());
if(!WorldSave.getCurrentSave().getWorld().collidingTile(tempBoundingRect))//if y path is possible
{
mob.moveBy(0, enemyMoveVector.y);
}
}
else
{
mob.moveBy(enemyMoveVector.x, 0);
}
}
else
{
mob.moveBy(enemyMoveVector.x, enemyMoveVector.y);
}
if (player.collideWith(mob)) {
player.setAnimation(CharacterSprite.AnimationTypes.Attack);
mob.setAnimation(CharacterSprite.AnimationTypes.Attack);
@@ -176,19 +200,7 @@ public class WorldStage extends GameStage implements SaveFileContent {
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);
return WorldSave.getCurrentSave().getWorld().collidingTile(boundingRect);
}
private void HandleMonsterSpawn(float delta) {
@@ -216,12 +228,25 @@ public class WorldStage extends GameStage implements SaveFileContent {
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);
for(int j=0;j<10;j++)
{
spawnPos.setLength(unit + (unit * 3) * rand.nextFloat());
spawnPos.setAngleDeg(360 * rand.nextFloat());
for(int i=0;i<10;i++)
{
boolean enemyXIsBigger=sprite.getX()>player.getX();
boolean enemyYIsBigger=sprite.getY()>player.getY();
sprite.setX(player.getX() + spawnPos.x+(i*sprite.getWidth()*(enemyXIsBigger?1:-1)));//maybe find a better way to get spawn points
sprite.setY(player.getY() + spawnPos.y+(i*sprite.getHeight()*(enemyYIsBigger?1:-1)));
if(sprite.getData().flying || !WorldSave.getCurrentSave().getWorld().collidingTile(sprite.boundingRect()))
{
enemies.add(Pair.of(globalTimer,sprite));
foregroundSprites.addActor(sprite);
return;
}
int g=0;
}
}
}
@Override

View File

@@ -64,6 +64,18 @@ public class Config {
}
if(settingsData.videomode == null || settingsData.videomode.isEmpty())
settingsData.videomode="720p";
//reward card display fine tune
if(settingsData.rewardCardAdj == null || settingsData.rewardCardAdj == 0f)
settingsData.rewardCardAdj=1f;
//tooltip fine tune
if(settingsData.cardTooltipAdj == null || settingsData.cardTooltipAdj == 0f)
settingsData.cardTooltipAdj=1f;
//reward card display fine tune landscape
if(settingsData.rewardCardAdjLandscape == null || settingsData.rewardCardAdjLandscape == 0f)
settingsData.rewardCardAdjLandscape=1f;
//tooltip fine tune landscape
if(settingsData.cardTooltipAdjLandscape == null || settingsData.cardTooltipAdjLandscape == 0f)
settingsData.cardTooltipAdjLandscape=1f;
this.plane = settingsData.plane;
currentConfig = this;

View File

@@ -52,6 +52,27 @@ public class Controls {
return ret;
}
static public SelectBox newComboBox(Float[] text, float item, Function<Object, Void> func) {
SelectBox ret = new SelectBox<Float>(GetSkin());
ret.getStyle().listStyle.selection.setTopHeight(4);
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.getList().setAlignment(Align.center);
ret.setSelected(item);
ret.setAlignment(Align.right);
return ret;
}
static public TextField newTextField(String text) {
return new TextField(text, GetSkin());
}

View File

@@ -54,6 +54,8 @@ public abstract class DrawOnPixmap {
frameBuffer.end();
texture.dispose();
batch.dispose();
if (bigText) //don't know why this is needed to circumvent bug getting default size for the same pixelfont
Controls.getBitmapFont("default");
}
}

View File

@@ -1,6 +1,8 @@
package forge.adventure.util;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.utils.Array;
import forge.Forge;
import forge.adventure.character.EnemySprite;

View File

@@ -146,15 +146,20 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
PaperCard card = ImageUtil.getPaperCardFromImageKey(reward.getCard().getImageKey(false));
File frontFace = ImageKeys.getImageFile(card.getCardImageKey());
if (frontFace != null) {
if (!Forge.getAssets().manager().contains(frontFace.getPath())) {
Forge.getAssets().manager().load(frontFace.getPath(), Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(frontFace.getPath());
count+=1;
}
Texture front = Forge.getAssets().manager().get(frontFace.getPath(), Texture.class, false);
if (front != null) {
setCardImage(front);
} else {
try {
if (!Forge.getAssets().manager().contains(frontFace.getPath())) {
Forge.getAssets().manager().load(frontFace.getPath(), Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(frontFace.getPath());
count+=1;
}
Texture front = Forge.getAssets().manager().get(frontFace.getPath(), Texture.class, false);
if (front != null) {
setCardImage(front);
} else {
loaded = false;
}
} catch (Exception e) {
System.err.println("Failed to load image: "+frontFace.getPath());
loaded = false;
}
} else {
@@ -166,10 +171,14 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
PaperCard cardBack = ImageUtil.getPaperCardFromImageKey(reward.getCard().getImageKey(true));
File backFace = ImageKeys.getImageFile(cardBack.getCardAltImageKey());
if (backFace != null) {
if (!Forge.getAssets().manager().contains(backFace.getPath())) {
Forge.getAssets().manager().load(backFace.getPath(), Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(backFace.getPath());
ImageCache.updateSynqCount(backFace, 1);
try {
if (!Forge.getAssets().manager().contains(backFace.getPath())) {
Forge.getAssets().manager().load(backFace.getPath(), Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(backFace.getPath());
ImageCache.updateSynqCount(backFace, 1);
}
} catch (Exception e) {
System.err.println("Failed to load image: "+backFace.getPath());
}
}
}
@@ -178,18 +187,23 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
File lookup = ImageKeys.hasSetLookup(imagePath) ? ImageKeys.setLookUpFile(imagePath, imagePath+"border") : null;
int count = 0;
if (lookup != null) {
if (!Forge.getAssets().manager().contains(lookup.getPath())) {
Forge.getAssets().manager().load(lookup.getPath(), Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(lookup.getPath());
count+=1;
}
Texture replacement = Forge.getAssets().manager().get(lookup.getPath(), Texture.class, false);
if (replacement != null) {
setCardImage(replacement);
} else {
try {
if (!Forge.getAssets().manager().contains(lookup.getPath())) {
Forge.getAssets().manager().load(lookup.getPath(), Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(lookup.getPath());
count += 1;
}
Texture replacement = Forge.getAssets().manager().get(lookup.getPath(), Texture.class, false);
if (replacement != null) {
setCardImage(replacement);
} else {
loaded = false;
}
ImageCache.updateSynqCount(lookup, count);
} catch (Exception e) {
System.err.println("Failed to load image: "+lookup.getPath());
loaded = false;
}
ImageCache.updateSynqCount(lookup, count);
} else if (!ImageCache.imageKeyFileExists(reward.getCard().getImageKey(false))) {
//Cannot find an image file, set up a rendered card until (if) a file is downloaded.
T = renderPlaceholder(getGraphics(), reward.getCard()); //Now we can render the card.
@@ -361,12 +375,17 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
float fW = x > y ? x : y;
float fH = x > y ? y : x;
float mul = fW/fH < AR ? AR/(fW/fH) : (fW/fH)/AR;
if (fW/fH >= 2f) {//tall display
mul = (fW/fH) - ((fW/fH)/AR);
if ((fW/fH) >= 2.1f && (fW/fH) < 2.3f)
mul *= 0.9f;
else if ((fW/fH) > 2.3) //ultrawide 21:9 Galaxy Fold, Huawei X2, Xperia 1
mul *= 0.8f;
Float custom = Forge.isLandscapeMode() ? Config.instance().getSettingData().cardTooltipAdjLandscape : Config.instance().getSettingData().cardTooltipAdj;
if (custom != null && custom != 1f) {
mul *= custom;
} else {
if (fW/fH >= 2f) {//tall display
mul = (fW/fH) - ((fW/fH)/AR);
if ((fW/fH) >= 2.1f && (fW/fH) < 2.2f)
mul *= 0.9f;
else if ((fW/fH) > 2.2f) //ultrawide 21:9 Galaxy Fold, Huawei X2, Xperia 1
mul *= 0.8f;
}
}
if (Forge.isLandscapeMode())
drawable.setMinSize(newW*mul, newH);

View File

@@ -10,11 +10,7 @@ import com.badlogic.gdx.maps.tiled.TiledMapTile;
import com.badlogic.gdx.maps.tiled.TiledMapTileSet;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.tiles.AnimatedTiledMapTile;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.SerializationException;
import com.badlogic.gdx.utils.XmlReader;
import com.badlogic.gdx.utils.*;
import forge.Forge;
import java.io.File;

View File

@@ -10,7 +10,6 @@ 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;
@@ -29,7 +28,7 @@ public class UIActor extends Group {
setWidth(data.width);
setHeight(data.height);
for (OrderedMap<String, String> element : new Array.ArrayIterator<>(data.elements)) {
for (OrderedMap<String, String> element : data.elements) {
String type = element.get("type");
Actor newActor;
if (type == null) {

View File

@@ -0,0 +1,154 @@
package forge.adventure.world;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import forge.adventure.data.BiomeStructureData;
import forge.adventure.util.Config;
import java.util.HashMap;
public class BiomeStructure {
private BiomeStructureData data;
long seed;
private int biomeWidth;
private int biomeHeight;
private int dataMap[][];
private boolean collisionMap[][];
boolean init=false;
private TextureAtlas structureAtlas;
public ColorMap image;
private final static int MAXIMUM_WAVEFUNCTIONSIZE=50;
public BiomeStructure(BiomeStructureData data,long seed,int width,int height)
{
this.data=data;
this.seed=seed;
this.biomeWidth = width;
this.biomeHeight = height;
}
public TextureAtlas atlas() {
if(structureAtlas==null)
{
try
{
structureAtlas = Config.instance().getAtlas(data.structureAtlasPath);
}
catch (Exception e)
{
e.printStackTrace();
}
}
return structureAtlas;
}
public int structureObjectCount() {
return data.mappingInfo.length;
}
public int objectID(int x, int y) {
if(!init)
{
initialize();
}
if(x>=dataMap.length||x<0||y<0||y>=dataMap[0].length)
return -1;
return dataMap[x][y];
}
public void initialize(ColorMap sourceImage,ColorMap maskImage) {
long currentTime = System.currentTimeMillis();
init=true;
int targetWidth=(int) (data.width* biomeWidth);
int targetHeight=(int) (data.width* biomeWidth);
dataMap=new int[targetWidth][ targetHeight];
collisionMap=new boolean[targetWidth][ targetHeight];
ColorMap finalImage=new ColorMap(targetWidth, targetHeight);
HashMap<Integer,Integer> colorIdMap=new HashMap<>();
for(int i=0;i<data.mappingInfo.length;i++)
{
colorIdMap.put(Integer.parseInt(data.mappingInfo[i].color,16),i);
}
for(int mx=0;mx<targetWidth;mx+=Math.min(targetWidth-mx,MAXIMUM_WAVEFUNCTIONSIZE))
{
for(int my=0;my<targetWidth;my+=Math.min(targetHeight-my,MAXIMUM_WAVEFUNCTIONSIZE))
{
OverlappingModel model= new OverlappingModel(sourceImage,data.N,Math.min(targetWidth-mx,MAXIMUM_WAVEFUNCTIONSIZE), Math.min(targetHeight-my,MAXIMUM_WAVEFUNCTIONSIZE),data.periodicInput,data.periodicOutput,data.symmetry,data.ground);
boolean suc=false;
for(int i=0;i<10&&!suc;i++)
suc=model.run((int) seed+(i*5355)+mx*my,0);
if(!suc)
{
for(int x=0;x<dataMap.length;x++)
for(int y=0;y<dataMap[x].length;y++)
dataMap[mx+x][my+y]=-1;
return;
}
image=model.graphics();
for(int x=0;x<image.getWidth();x++)
{
for(int y=0;y<image.getHeight();y++)
{
boolean isWhitePixel=maskImage!=null&&(maskImage.getColor((int) ((mx+x)*maskImage.getWidth()/(float)targetWidth),(int)((my+y)*(maskImage.getHeight()/(float)targetHeight)) )).equals(Color.WHITE);
if(isWhitePixel)
finalImage.setColor(mx+x,my+y, Color.WHITE);
else
finalImage.setColor(mx+x,my+y, image.getColor(x,y));
int rgb=Color.rgb888(image.getColor(x,y)) ;
if(isWhitePixel||!colorIdMap.containsKey(rgb))
{
dataMap[mx+x][my+y]=-1;
}
else
{
dataMap[mx+x][my+y]=colorIdMap.get(rgb);
collisionMap[mx+x][my+y]=data.mappingInfo[colorIdMap.get(rgb)].collision;
}
}
}
}
image=finalImage;
}
}
public void initialize() {
initialize(sourceImage(),maskImage());
}
public ColorMap sourceImage() {
return new ColorMap(Config.instance().getFile(data.sourcePath));
}
public String sourceImagePath() {
return (Config.instance().getFilePath(data.sourcePath));
}
private ColorMap maskImage() {
return new ColorMap(Config.instance().getFile(data.maskPath));
}
public BiomeStructureData.BiomeStructureDataMapping[] mapping() {
return data.mappingInfo;
}
public boolean collision(int x, int y) {
if(!init)
{
initialize();
}
if(x>=collisionMap.length||x<0||y<0||y>=collisionMap[0].length)
return false;
return collisionMap[x][y];
}
public String maskImagePath() {
return (Config.instance().getFilePath(data.maskPath));
}
}

View File

@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.IntMap;
import forge.adventure.data.BiomeData;
import forge.adventure.data.BiomeStructureData;
import forge.adventure.data.BiomeTerrainData;
import forge.adventure.util.Config;
import forge.gui.FThreads;
@@ -19,7 +20,7 @@ import java.util.ArrayList;
public class BiomeTexture implements Serializable {
private final BiomeData data;
private final int tileSize;
public Pixmap emptyPixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
public static Pixmap emptyPixmap = null;
ArrayList<ArrayList<Pixmap>> images = new ArrayList<>();
ArrayList<ArrayList<Pixmap>> smallImages = new ArrayList<>();
ArrayList<IntMap<Pixmap>> edgeImages = new ArrayList<>();
@@ -45,7 +46,6 @@ public class BiomeTexture implements Serializable {
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
Pixmap completePicture = null;
if (images != null) {
for (ArrayList<Pixmap> val : images) {
@@ -79,22 +79,49 @@ public class BiomeTexture implements Serializable {
edgeImages = new ArrayList<>();
ArrayList<TextureAtlas.AtlasRegion> regions =new ArrayList<>();
ArrayList<TextureAtlas> source =new ArrayList<>();
regions.add(Config.instance().getAtlas(data.tilesetAtlas).findRegion(data.tilesetName));
source.add(Config.instance().getAtlas(data.tilesetAtlas));
if(data.terrain!=null)
{
for(BiomeTerrainData terrain:data.terrain)
{
regions.add(Config.instance().getAtlas(data.tilesetAtlas).findRegion(terrain.spriteName));
TextureAtlas.AtlasRegion region = Config.instance().getAtlas(data.tilesetAtlas).findRegion(terrain.spriteName);
if(region==null)
{
System.err.print("Can not find sprite "+terrain.spriteName);
continue;
}
regions.add(region);
source.add(Config.instance().getAtlas(data.tilesetAtlas));
}
}
if(data.structures!=null)
{
for(BiomeStructureData structureData:data.structures)
{
BiomeStructure structure=new BiomeStructure(structureData,0,0,0);
TextureAtlas atlas=structure.atlas ();
for(BiomeStructureData.BiomeStructureDataMapping mapping:structure.mapping())
{
TextureAtlas.AtlasRegion region = atlas.findRegion(mapping.name);
if(region==null)
{
System.err.print("Can not find sprite "+mapping.name);
continue;
}
regions.add(region);
source.add(atlas);
}
}
}
for (TextureAtlas.AtlasRegion region : regions) {
ArrayList<Pixmap> pics = new ArrayList<>();
ArrayList<Pixmap> spics = new ArrayList<>();
if (completePicture == null) {
if(!region.getTexture().getTextureData().isPrepared())
region.getTexture().getTextureData().prepare();
completePicture = region.getTexture().getTextureData().consumePixmap();
}
Pixmap completePicture = region.getTexture().getTextureData().consumePixmap();
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 3; x++) {
int px = region.getRegionX() + (x * tileSize);
@@ -117,6 +144,7 @@ public class BiomeTexture implements Serializable {
smallImages.add(spics);
edgeImages.add(new IntMap<>());
completePicture.dispose();
}
}
});
@@ -124,6 +152,8 @@ public class BiomeTexture implements Serializable {
public Pixmap getPixmap(int biomeSubIndex) {
if (biomeSubIndex >= edgeImages.size() || biomeSubIndex < 0) {
if(emptyPixmap==null)
emptyPixmap=new Pixmap(1, 1, Pixmap.Format.RGBA8888);
return emptyPixmap;
}
return images.get(biomeSubIndex).get(BigPictures.Center.value);

View File

@@ -0,0 +1,49 @@
package forge.adventure.world;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
public class ColorMap
{
private final int width;
private final int height;
private final Color[] data;
public ColorMap(int w,int h)
{
width=w;
height=h;
data=new Color[w*h];
for(int i=0;i<w*h;i++)
data[i]=new Color();
}
public ColorMap(FileHandle file) {
Pixmap pdata=new Pixmap(file);
width=pdata.getWidth();
height=pdata.getHeight();
data=new Color[width*height];
for(int y=0;y<height;y++)
for(int x=0;x<width;x++)
{
data[x+y*width]=new Color(pdata.getPixel(x,y));
}
pdata.dispose();
}
public int getWidth() {
return width;
}
public int getHeight()
{
return height;
}
public Color getColor(int x, int y) {
return data[x+y*width];
}
public void setColor(int x, int y, Color c) {
data[x+y*width].set(c);
}
}

View File

@@ -0,0 +1,226 @@
package forge.adventure.world;
import java.util.Random;
abstract class Model {
protected boolean[][] wave;
protected int[][][] propagator;
int[][][] compatible;
protected int[] observed;
int[] stack;
int stacksize;
protected Random random;
protected int FMX, FMY, T;
protected boolean periodic;
protected Double[] weights;
double[] weightLogWeights;
int[] sumsOfOnes;
double sumOfWeights, sumOfWeightLogWeights, startingEntropy;
double[] sumsOfWeights, sumsOfWeightLogWeights, entropies;
private double[] distribution;
protected Model(int width, int height) {
this.FMX = width;
this.FMY = height;
}
protected abstract boolean onBoundary(int x, int y);
public abstract ColorMap graphics();
protected static int[] DX = { -1, 0, 1, 0 };
protected static int[] DY = { 0, 1, 0, -1 };
static int[] oppposite = { 2, 3, 0, 1 };
static int randomIndice(double[] arr, double r) {
double sum = 0;
for (int j = 0; j < arr.length; j++) sum += arr[j];
for (int j = 0; j < arr.length; j++) arr[j] /= sum;
int i = 0;
double x = 0;
while (i < arr.length) {
x += arr[i];
if (r <= x) return i;
i++;
}
return 0;
}
public static long toPower(int a, int n) {
long product = 1;
for (int i = 0; i < n; i++) product *= a;
return product;
}
void init() {
this.wave = new boolean[this.FMX * this.FMY][];
this.compatible = new int[this.wave.length][][];
for (int i = 0; i < wave.length; i++) {
this.wave[i] = new boolean[this.T];
this.compatible[i] = new int[this.T][];
for (int t = 0; t < this.T; t++) this.compatible[i][t] = new int[4];
}
this.weightLogWeights = new double[this.T];
this.distribution = new double[this.T];
this.sumOfWeights = 0;
this.sumOfWeightLogWeights = 0;
for (int t = 0; t < this.T; t++) {
this.weightLogWeights[t] = this.weights[t] * Math.log(this.weights[t]);
this.sumOfWeights += this.weights[t];
this.sumOfWeightLogWeights += this.weightLogWeights[t];
}
this.startingEntropy =
Math.log(this.sumOfWeights) -
this.sumOfWeightLogWeights /
this.sumOfWeights;
this.sumsOfOnes = new int[this.FMX * this.FMY];
this.sumsOfWeights = new double[this.FMX * this.FMY];
this.sumsOfWeightLogWeights = new double[this.FMX * this.FMY];
this.entropies = new double[this.FMX * this.FMY];
this.stack = new int[(this.wave.length * this.T)*2];
this.stacksize = 0;
}
Boolean observe() {
double min = 1e+3;
int argmin = -1;
for (int i = 0; i < this.wave.length; i++) {
if (this.onBoundary(i % this.FMX, i / this.FMX)) continue;
int amount = this.sumsOfOnes[i];
if (amount == 0) return false;
double entropy = this.entropies[i];
if (amount > 1 && entropy <= min) {
double noise = 1e-6 * this.random.nextDouble();
if (entropy + noise < min) {
min = entropy + noise;
argmin = i;
}
}
}
if (argmin == -1) {
this.observed = new int[this.FMX * this.FMY];
for (int i = 0; i < this.wave.length; i++) for (int t = 0; t <
this.T; t++) if (this.wave[i][t]) {
this.observed[i] = t;
break;
}
return true;
}
for (int t = 0; t < this.T; t++) distribution[t] =
this.wave[argmin][t] ? this.weights[t] : 0;
int r = Model.randomIndice(distribution, this.random.nextDouble());
boolean[] w = this.wave[argmin];
for (int t = 0; t < this.T; t++) if (w[t] != (t == r)) this.ban(argmin, t);
return null;
}
protected void ban(int i, int t) {
this.wave[i][t] = false;
int[] comp = this.compatible[i][t];
for (int d = 0; d < 4; d++) comp[d] = 0;
this.stack[this.stacksize]=i;
this.stack[this.stacksize+1]=t;
this.stacksize+=2;
this.sumsOfOnes[i] -= 1;
this.sumsOfWeights[i] -= this.weights[t];
this.sumsOfWeightLogWeights[i] -= this.weightLogWeights[t];
double sum = this.sumsOfWeights[i];
this.entropies[i] = Math.log(sum) - this.sumsOfWeightLogWeights[i] / sum;
}
protected void propagate() {
while (this.stacksize >= 2) {
int i1 = this.stack[this.stacksize - 2];
int x1 = i1 % this.FMX;
int y1 = i1 / this.FMX;
int stack2 = this.stack[this.stacksize - 1];
this.stacksize-=2;
for (int d = 0; d < 4; d++) {
int dx = Model.DX[d], dy = Model.DY[d];
int x2 = x1 + dx, y2 = y1 + dy;
if (this.onBoundary(x2, y2)) continue;
if (x2 < 0) x2 += this.FMX; else if (x2 >= this.FMX) x2 -= this.FMX;
if (y2 < 0) y2 += this.FMY; else if (y2 >= this.FMY) y2 -= this.FMY;
int i2 = x2 + y2 * this.FMX;
int[] p = this.propagator[d][stack2];
int[][] compat = this.compatible[i2];
for (int l = 0; l < p.length; l++) {
int t2 = p[l];
int[] comp = compat[t2];
comp[d]--;
if (comp[d] == 0) this.ban(i2, t2);
}
}
}
}
public boolean run(int seed, int limit) {
if (this.wave == null) this.init();
this.Clear();
this.random = new Random(seed);
for (int l = 0; l < limit || limit == 0; l++) {
Boolean result = this.observe();
if (result != null)
return (boolean) result;
this.propagate();
}
return true;
}
protected void Clear() {
for (int i = 0; i < this.wave.length; i++) {
for (int t = 0; t < this.T; t++) {
this.wave[i][t] = true;
for (int d = 0; d < 4; d++) this.compatible[i][t][d] =
this.propagator[Model.oppposite[d]][t].length;
}
this.sumsOfOnes[i] = this.weights.length;
this.sumsOfWeights[i] = this.sumOfWeights;
this.sumsOfWeightLogWeights[i] = this.sumOfWeightLogWeights;
this.entropies[i] = this.startingEntropy;
}
}
}

View File

@@ -0,0 +1,293 @@
package forge.adventure.world;
import com.badlogic.gdx.graphics.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
public class OverlappingModel extends Model {
int N;
Integer[][] patterns;
int ground;
List<Color> colors;
@FunctionalInterface
interface Agrees<One, Two, Three, Four, Five> {
public Five apply(One one, Two two, Three three, Four four);
}
/**
* Creates a new instance of the Overlapping Model
* @param data BufferedImage data of source image.
* @param N Size of the patterns.
* @param width The width of the generation (in pixels).
* @param height The height of the generation (in pixels).
* @param periodicInput Whether the source image is to be considered as periodic (repeatable).
* @param periodicOutput Whether the generation should be periodic (repeatable).
* @param symmetry Allowed symmetries from 1 (no symmetry) to 8 (all mirrored / rotated variations).
* @param ground Id of the specific pattern to use as the bottom of the generation.
*/
public OverlappingModel(
ColorMap data,
int N,
int width,
int height,
boolean periodicInput,
boolean periodicOutput,
int symmetry,
int ground
) {
super(width, height);
this.N = N;
this.periodic = periodicOutput;
int SMX = data.getWidth(), SMY = data.getHeight();
Integer[][] sample = new Integer[SMX][SMY];
this.colors = new ArrayList<Color>();
for (int y = 0; y < SMY; y++) for (int x = 0; x < SMX; x++) {
Color color = data.getColor(x, y);
if(color==null)
break;
int i = 0;
for (Color c : colors) {
if (c.equals(color)) break;
i++;
}
if (i == colors.size()) colors.add(color);
sample[x][y] = i;
}
int C = this.colors.size();
long W = OverlappingModel.toPower(C, this.N * this.N);
Function<BiFunction<Integer, Integer, Integer>, Integer[]> pattern =
(BiFunction<Integer, Integer, Integer> f) -> {
Integer[] result = new Integer[this.N * this.N];
for (int y = 0; y < this.N; y++) for (int x = 0; x <
this.N; x++) result[x + y * this.N] = f.apply(x, y);
return result;
};
BiFunction<Integer, Integer, Integer[]> patternFromSample =
(Integer x, Integer y) -> pattern.apply(
(Integer dx, Integer dy) -> sample[(x + dx) % SMX][(y + dy) % SMY]
);
Function<Integer[], Integer[]> rotate =
(Integer[] p) -> pattern.apply(
(Integer x, Integer y) -> p[this.N - 1 - y + x * this.N]
);
Function<Integer[], Integer[]> reflect =
(Integer[] p) -> pattern.apply(
(Integer x, Integer y) -> p[this.N - 1 - x + y * this.N]
);
Function<Integer[], Long> index =
(Integer[] p) -> {
long result = 0, power = 1;
for (int i = 0; i < p.length; i++) {
result += p[p.length - 1 - i] * power;
power *= C;
}
return result;
};
Function<Long, Integer[]> patternFromIndex =
(Long ind) -> {
long residue = ind, power = W;
Integer[] result = new Integer[this.N * this.N];
for (int i = 0; i < result.length; i++) {
power /= C;
int count = 0;
while (residue >= power) {
residue -= power;
count++;
}
result[i] = count;
}
return result;
};
HashMap<Long, Integer> weights = new HashMap<Long, Integer>();
List<Long> ordering = new ArrayList<Long>();
for (int y = 0; y < (periodicInput ? SMY : SMY - N + 1); y++) for (int x =
0; x < (periodicInput ? SMX : SMX - this.N + 1); x++) {
Integer[][] ps = new Integer[8][];
ps[0] = patternFromSample.apply(x, y);
ps[1] = reflect.apply(ps[0]);
ps[2] = rotate.apply(ps[0]);
ps[3] = reflect.apply(ps[2]);
ps[4] = rotate.apply(ps[2]);
ps[5] = reflect.apply(ps[4]);
ps[6] = rotate.apply(ps[4]);
ps[7] = reflect.apply(ps[6]);
for (int k = 0; k < symmetry; k++) {
long ind = index.apply(ps[k]);
if (weights.containsKey(ind)) weights.put(
ind,
weights.get(ind) + 1
); else {
weights.put(ind, 1);
ordering.add(ind);
}
}
}
this.T = weights.size();
this.ground = (ground + this.T) % this.T;
this.patterns = new Integer[this.T][];
this.weights = new Double[this.T];
int counter = 0;
for (long w : ordering) {
this.patterns[counter] = patternFromIndex.apply(w);
this.weights[counter] = (double) weights.get(w);
// System.out.println(this.weights[counter]);
// weights[counter] = weights[(int) w];
counter++;
}
Agrees<Integer[], Integer[], Integer, Integer, Boolean> agrees =
(Integer[] p1, Integer[] p2, Integer dx, Integer dy) -> {
int xmin = dx < 0 ? 0 : dx;
int xmax = dx < 0 ? dx + N : N;
int ymin = dy < 0 ? 0 : dy;
int ymax = dy < 0 ? dy + N : N;
for (int y = ymin; y < ymax; y++) for (int x = xmin; x < xmax; x++) if (
p1[x + this.N * y] != p2[x - dx + this.N * (y - dy)]
) return false;
return true;
};
this.propagator = new int[4][][];
// System.out.println(this.T);
for (int d = 0; d < 4; d++) {
this.propagator[d] = new int[this.T][];
for (int t = 0; t < this.T; t++) {
List<Integer> list = new ArrayList<Integer>();
for (int t2 = 0; t2 < this.T; t2++) if (
agrees.apply(
this.patterns[t],
this.patterns[t2],
Model.DX[d],
Model.DY[d]
)
) list.add(t2);
this.propagator[d][t] = new int[list.size()];
for (int c = 0; c < list.size(); c++) this.propagator[d][t][c] =
list.get(c);
}
}
}
@Override
protected boolean onBoundary(int x, int y) {
return (
!this.periodic &&
(x + this.N > this.FMX || y + this.N > this.FMY || x < 0 || y < 0)
);
}
/**
* Returns a new BufferedImage generated by the model.
* Requires Run() to have been run.
*/
@Override
public ColorMap graphics() {
ColorMap result = new ColorMap(
this.FMX,
this.FMY
);
if (this.observed != null) {
for (int y = 0; y < this.FMY; y++) {
int dy = y < this.FMY - this.N + 1 ? 0 : this.N - 1;
for (int x = 0; x < this.FMX; x++) {
int dx = x < this.FMX - this.N + 1 ? 0 : this.N - 1;
Color c =
this.colors.get(
this.patterns[this.observed[x - dx + (y - dy) * this.FMX]][dx +
dy *
this.N]
);
result.setColor(x, y, c);
}
}
} else {
for (int i = 0; i < this.wave.length; i++) {
float contributors = 0, r = 0, g = 0, b = 0;
int x = i % this.FMX, y = i / this.FMX;
for (int dy = 0; dy < this.N; dy++) for (int dx = 0; dx <
this.N; dx++) {
int sx = x - dx;
if (sx < 0) sx += this.FMX;
int sy = y - dy;
if (sy < 0) sy += this.FMY;
int s = sx + sy * this.FMX;
if (this.onBoundary(sx, sy)) continue;
for (int t = 0; t < this.T; t++) if (wave[s][t]) {
contributors++;
Color color = this.colors.get(this.patterns[t][dx + dy * this.N]);
r += color.r;
g += color.g;
b += color.b;
}
}
Color c = new Color(
r / contributors,
g / contributors,
b / contributors,1f
);
result.setColor(x, y, c);
}
}
return result;
}
protected void Clear() {
super.Clear();
if (this.ground != 0) {
for (int x = 0; x < this.FMX; x++) {
for (int t = 0; t < this.T; t++) if (t != this.ground) this.ban(
x + (this.FMY - 1) * this.FMX,
t
);
for (int y = 0; y < this.FMY - 1; y++) this.ban(
x + y * this.FMX,
this.ground
);
}
this.propagate();
}
}
}

View File

@@ -0,0 +1,337 @@
package forge.adventure.world;
import com.badlogic.gdx.graphics.Color;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.IntStream;
public class SimpleTiledModel extends Model {
List<Color[]> tiles;
List<String> tilenames;
int tilesize;
boolean black;
/**
* Create a new instance of a Simple Tiled Model.
* @param tilesize Size of the tile images in pixels.
* @param tileSymmetries Array of Map of tilenames and their symmetries.
* @param neighborData Array of Map of left and right neighbor combinations.
* @param subsetData Map of Subset definitions.
* @param tileData Map of tile image data indexed by tilename.
* @param subsetName Name of the subset in subsetData to use.
* @param width Output width in tiles.
* @param height Output height in tiles.
* @param periodic Should the output generation be tileable.
* @param black
* @param unique
*/
public SimpleTiledModel(
int tilesize,
List<Map<String, String>> tileSymmetries,
List<Map<String, String>> neighborData,
Map<String, String[]> subsetData,
Map<String, ColorMap> tileData,
String subsetName,
int width,
int height,
boolean periodic,
boolean black,
boolean unique
) {
super(width, height);
this.periodic = periodic;
this.black = black;
this.tilesize = tilesize;
List<String> subset = null;
if (
subsetName != null &&
subsetData != null &&
subsetData.containsKey(subsetName)
) {
subset = Arrays.asList(subsetData.get(subsetName));
}
Function<BiFunction<Integer, Integer, Color>, Color[]> tile =
(BiFunction<Integer, Integer, Color> f) -> {
Color[] result = new Color[this.tilesize * this.tilesize];
for (int y = 0; y < this.tilesize; y++) for (int x = 0; x <
this.tilesize; x++) result[x + y * tilesize] = f.apply(x, y);
return result;
};
Function<Color[], Color[]> rotate =
(Color[] array) -> tile.apply(
(Integer x, Integer y) -> array[this.tilesize -
1 -
y +
x *
this.tilesize]
);
this.tiles = new ArrayList<Color[]>();
this.tilenames = new ArrayList<String>();
List<Double> tempStationary = new ArrayList<Double>();
List<Integer[]> action = new ArrayList<Integer[]>();
HashMap<String, Integer> firstOccurrence = new HashMap<String, Integer>();
for (Map<String, String> xtile : tileSymmetries) {
String tilename = xtile.get("name");
Function<Integer, Integer> a, b;
int cardinality;
String sym = xtile.getOrDefault("symmetry", "X");
if (subset != null && !subset.contains(tilename)) continue;
switch (sym) {
case "L":
cardinality = 4;
a = (Integer i) -> (i + 1) % 4;
b = (Integer i) -> (i % 2) == 0 ? i + 1 : i - 1;
break;
case "T":
cardinality = 4;
a = (Integer i) -> (i + 1) % 4;
b = (Integer i) -> (i % 2) == 0 ? i : 4 - i;
break;
case "I":
cardinality = 2;
a = (Integer i) -> 1 - i;
b = (Integer i) -> i;
break;
case "\\":
cardinality = 2;
a = (Integer i) -> 1 - i;
b = (Integer i) -> 1 - i;
break;
default:
cardinality = 1;
a = (Integer i) -> i;
b = (Integer i) -> i;
break;
}
this.T = action.size();
firstOccurrence.put(tilename, this.T);
Integer[][] map = new Integer[cardinality][];
for (int t = 0; t < cardinality; t++) {
map[t] = new Integer[8];
map[t][0] = t;
map[t][1] = a.apply(t);
map[t][2] = a.apply(a.apply(t));
map[t][3] = a.apply(a.apply(a.apply(t)));
map[t][4] = b.apply(t);
map[t][5] = b.apply(a.apply(t));
map[t][6] = b.apply(a.apply(a.apply(t)));
map[t][7] = b.apply(a.apply(a.apply(a.apply(t))));
for (int s = 0; s < 8; s++) map[t][s] += this.T;
action.add(map[t]);
}
if (unique) {
for (int t = 0; t < cardinality; t++) {
ColorMap xtileData = tileData.get(tilename);
this.tiles.add(
tile.apply(
(Integer x, Integer y) -> (xtileData.getColor(x, y))
)
);
this.tilenames.add(String.format("%s %s", tilename, t));
}
} else {
ColorMap xtileData = tileData.get(tilename);
this.tiles.add(
tile.apply(
(Integer x, Integer y) -> (xtileData.getColor(x, y))
)
);
this.tilenames.add(String.format("%s 0", tilename));
for (int t = 1; t < cardinality; t++) {
this.tiles.add(rotate.apply(this.tiles.get(this.T + t - 1)));
this.tilenames.add(String.format("%s %s", tilename, t));
}
}
for (int t = 0; t < cardinality; t++) tempStationary.add(
Double.valueOf(xtile.getOrDefault("weight", "1.0"))
);
}
this.T = action.size();
this.weights = tempStationary.toArray(new Double[0]);
this.propagator = new int[4][][];
boolean[][][] tempPropagator = new boolean[4][][];
for (int d = 0; d < 4; d++) {
tempPropagator[d] = new boolean[this.T][];
this.propagator[d] = new int[this.T][];
for (int t = 0; t < this.T; t++) tempPropagator[d][t] =
new boolean[this.T];
}
for (Map<String, String> xneighbor : neighborData) {
String[] left = Arrays
.stream(xneighbor.get("left").split(" "))
.filter(x -> !x.isEmpty())
.toArray(String[]::new);
String[] right = Arrays
.stream(xneighbor.get("right").split(" "))
.filter(x -> !x.isEmpty())
.toArray(String[]::new);
if (
subset != null &&
(!subset.contains(left[0]) || !subset.contains(right[0]))
) continue;
int L = action.get(firstOccurrence.get(left[0]))[left.length == 1 ? 0
: Integer.valueOf(left[1])];
int D = action.get(L)[1];
int R = action.get(firstOccurrence.get(right[0]))[right.length == 1 ? 0
: Integer.valueOf(right[1])];
int U = action.get(R)[1];
tempPropagator[0][R][L] = true;
tempPropagator[0][action.get(R)[6]][action.get(L)[6]] = true;
tempPropagator[0][action.get(L)[4]][action.get(R)[4]] = true;
tempPropagator[0][action.get(L)[2]][action.get(R)[2]] = true;
tempPropagator[1][U][D] = true;
tempPropagator[1][action.get(D)[6]][action.get(U)[6]] = true;
tempPropagator[1][action.get(U)[4]][action.get(D)[4]] = true;
tempPropagator[1][action.get(D)[2]][action.get(U)[2]] = true;
}
for (int t2 = 0; t2 < this.T; t2++) for (int t1 = 0; t1 < this.T; t1++) {
tempPropagator[2][t2][t1] = tempPropagator[0][t1][t2];
tempPropagator[3][t2][t1] = tempPropagator[1][t1][t2];
}
ArrayList<ArrayList<ArrayList<Integer>>> sparsePropagator = new ArrayList<ArrayList<ArrayList<Integer>>>();
for(int d = 0; d < 4; d++) {
sparsePropagator.add(d, new ArrayList<ArrayList<Integer>>());
for (int t = 0; t < this.T; t++)
sparsePropagator.get(d).add(t, new ArrayList<Integer>());
}
for (int d = 0; d < 4; d++) for (int t1 = 0; t1 < this.T; t1++) {
ArrayList<Integer> sp = sparsePropagator.get(d).get(t1);
boolean[] tp = tempPropagator[d][t1];
for (int t2 = 0; t2 < this.T; t2++) {
if (tp[t2]) sp.add(t2);
}
int ST = sp.size();
this.propagator[d][t1] = new int[ST];
for (int st = 0; st < ST; st++) this.propagator[d][t1][st] = sp.get(st);
}
}
@Override
protected boolean onBoundary(int x, int y) {
return !this.periodic && (x < 0 || y < 0 || x >= this.FMX || y >= this.FMY);
}
public String textOutput() {
StringBuilder result = new StringBuilder();
for (int y = 0; y < this.FMY; y++) {
for (int x = 0; x < this.FMX; x++)
result.append(String.format("{%s}, ", this.tilenames.get(this.observed[x + y * this.FMX])));
result.append("\n");
}
return result.toString();
}
@Override
public ColorMap graphics() {
ColorMap result = new ColorMap(
this.FMX * this.tilesize,
this.FMY * this.tilesize
);
// System.out.println(this.observed);
if (this.observed != null) {
for (int x = 0; x < this.FMX; x++) for (int y = 0; y < this.FMY; y++) {
Color[] tile = this.tiles.get(this.observed[x + y * this.FMX]);
for (int yt = 0; yt < this.tilesize; yt++) for (int xt = 0; xt <
this.tilesize; xt++) {
Color c = tile[xt + yt * this.tilesize];
result.setColor(
x * this.tilesize + xt,
y * this.tilesize + yt,
c
);
}
}
} else {
for (int x = 0; x < this.FMX; x++) for (int y = 0; y < this.FMY; y++) {
boolean[] a = this.wave[x + y * this.FMX];
int amount = IntStream
.range(0, a.length)
.map(idx -> a[idx] ? 1 : 0)
.sum();
double lambda =
1.0 /
IntStream
.range(0, this.T)
.filter(idx -> a[idx])
.mapToDouble(idx -> this.weights[idx])
.sum();
for (int yt = 0; yt < this.tilesize; yt++) for (int xt = 0; xt <
this.tilesize; xt++) {
if (this.black && amount == this.T) result.setColor(
x * this.tilesize + xt,
y * this.tilesize * yt,
Color.BLACK
); else {
double r = 0, g = 0, b = 0;
for (int t = 0; t < this.T; t++) if (a[t]) {
Color c = this.tiles.get(t)[xt + yt * this.tilesize];
r += c.r * this.weights[t] * lambda;
g += c.g * this.weights[t] * lambda;
b += c.b * this.weights[t] * lambda;
}
Color newColor = new Color((float) r, (float) g, (float) b,1);
result.setColor(
x * tilesize + xt,
y * tilesize + yt,
newColor
);
}
}
}
}
return result;
}
}

View File

@@ -9,11 +9,7 @@ import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.Json;
import forge.adventure.data.BiomeData;
import forge.adventure.data.BiomeSpriteData;
import forge.adventure.data.BiomeTerrainData;
import forge.adventure.data.PointOfInterestData;
import forge.adventure.data.WorldData;
import forge.adventure.data.*;
import forge.adventure.pointofintrest.PointOfInterest;
import forge.adventure.pointofintrest.PointOfInterestMap;
import forge.adventure.scene.Scene;
@@ -22,21 +18,24 @@ import forge.adventure.util.Config;
import forge.adventure.util.Paths;
import forge.adventure.util.SaveFileContent;
import forge.adventure.util.SaveFileData;
import forge.gui.FThreads;
import forge.gui.GuiBase;
import forge.util.ThreadUtil;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.*;
/**
* Class that will create the world from the configuration
*/
public class World implements Disposable, SaveFileContent {
public class World implements Disposable, SaveFileContent {
private WorldData data;
private Pixmap biomeImage;
private long[][] biomeMap;
private int[][] terrainMap;
private static final int collisionBit = 0b10000000000000000000000000000000;
private static final int isStructureBit = 0b01000000000000000000000000000000;
private static final int terrainMask = collisionBit | isStructureBit;
private int width;
private int height;
private SpritesDataMap mapObjectIds;
@@ -44,19 +43,38 @@ public class World implements Disposable, SaveFileContent {
private BiomeTexture[] biomeTexture;
private long seed;
private final Random random = new Random();
private boolean worldDataLoaded=false;
private boolean worldDataLoaded = false;
private Texture globalTexture = null;
public Random getRandom()
{
public Random getRandom() {
return random;
}
static public int highestBiome(long biome) {
return (int) (Math.log(Long.highestOneBit(biome)) / Math.log(2));
}
public boolean collidingTile(Rectangle boundingRect) {
int xLeft = (int) boundingRect.getX() / getTileSize();
int yTop = (int) boundingRect.getY() / getTileSize();
int xRight = (int) ((boundingRect.getX() + boundingRect.getWidth()) / getTileSize());
int yBottom = (int) ((boundingRect.getY() + boundingRect.getHeight()) / getTileSize());
if (isColliding(xLeft, yTop))
return true;
if (isColliding(xLeft, yBottom))
return true;
if (isColliding(xRight, yBottom))
return true;
if (isColliding(xRight, yTop))
return true;
return false;
}
public void loadWorldData() {
if(worldDataLoaded)
if (worldDataLoaded)
return;
FileHandle handle = Config.instance().getFile(Paths.WORLD);
@@ -64,49 +82,51 @@ public class World implements Disposable, SaveFileContent {
this.data = (new Json()).fromJson(WorldData.class, rawJson);
biomeTexture = new BiomeTexture[data.GetBiomes().size() + 1];
int biomeIndex=0;
int biomeIndex = 0;
for (BiomeData biome : data.GetBiomes()) {
biomeTexture[biomeIndex] = new BiomeTexture(biome, data.tileSize);
biomeIndex++;
}
biomeTexture[biomeIndex] = new BiomeTexture(data.roadTileset, data.tileSize);
worldDataLoaded=true;
worldDataLoaded = true;
}
@Override
public void load(SaveFileData saveFileData) {
if(biomeImage!=null)
if (biomeImage != null)
biomeImage.dispose();
loadWorldData();
loadWorldData();
biomeImage=saveFileData.readPixmap("biomeImage");
biomeMap=(long[][])saveFileData.readObject("biomeMap");
terrainMap=(int[][])saveFileData.readObject("terrainMap");
width=saveFileData.readInt("width");
height=saveFileData.readInt("height");
biomeImage = saveFileData.readPixmap("biomeImage");
biomeMap = (long[][]) saveFileData.readObject("biomeMap");
terrainMap = (int[][]) saveFileData.readObject("terrainMap");
width = saveFileData.readInt("width");
height = saveFileData.readInt("height");
mapObjectIds = new SpritesDataMap(getChunkSize(), this.data.tileSize, this.data.width / getChunkSize());
mapObjectIds.load(saveFileData.readSubData("mapObjectIds"));
mapPoiIds = new PointOfInterestMap(getChunkSize(), this.data.tileSize, this.data.width / getChunkSize(),this.data.height / getChunkSize());
mapPoiIds = new PointOfInterestMap(getChunkSize(), this.data.tileSize, this.data.width / getChunkSize(), this.data.height / getChunkSize());
mapPoiIds.load(saveFileData.readSubData("mapPoiIds"));
seed=saveFileData.readLong("seed");
seed = saveFileData.readLong("seed");
}
@Override
public SaveFileData save() {
SaveFileData data=new SaveFileData();
SaveFileData data = new SaveFileData();
data.store("biomeImage",biomeImage);
data.storeObject("biomeMap",biomeMap);
data.storeObject("terrainMap",terrainMap);
data.store("width",width);
data.store("height",height);
data.store("mapObjectIds",mapObjectIds.save());
data.store("mapPoiIds",mapPoiIds.save());
data.store("seed",seed);
data.store("biomeImage", biomeImage);
data.storeObject("biomeMap", biomeMap);
data.storeObject("terrainMap", terrainMap);
data.store("width", width);
data.store("height", height);
data.store("mapObjectIds", mapObjectIds.save());
data.store("mapPoiIds", mapPoiIds.save());
data.store("seed", seed);
return data;
@@ -116,6 +136,7 @@ public class World implements Disposable, SaveFileContent {
public BiomeSpriteData getObject(int id) {
return mapObjectIds.get(id);
}
private class DrawingInformation {
private int neighbors;
@@ -130,17 +151,18 @@ public class World implements Disposable, SaveFileContent {
}
public void draw(Pixmap drawingPixmap) {
regions.drawPixmapOn(terrain,neighbors,drawingPixmap);
regions.drawPixmapOn(terrain, neighbors, drawingPixmap);
}
}
public Pixmap getBiomeSprite(int x, int y) {
if (x < 0 || y <= 0 || x >= width || y > height)
return new Pixmap(data.tileSize, data.tileSize, Pixmap.Format.RGBA8888);
long biomeIndex = getBiome(x, y);
int terrain = getTerrainIndex(x, y);
int biomeTerrain = getTerrainIndex(x, y);
Pixmap drawingPixmap = new Pixmap(data.tileSize, data.tileSize, Pixmap.Format.RGBA8888);
ArrayList<DrawingInformation> information=new ArrayList<>();
ArrayList<DrawingInformation> information = new ArrayList<>();
for (int i = 0; i < biomeTexture.length; i++) {
if ((biomeIndex & 1L << i) == 0) {
continue;
@@ -148,9 +170,8 @@ public class World implements Disposable, SaveFileContent {
BiomeTexture regions = biomeTexture[i];
if (x <= 0 || y <= 1 || x >= width - 1 || y >= height)//edge
{
return regions.getPixmap(terrain);
return regions.getPixmap(biomeTerrain);
}
int biomeTerrain=Math.min(regions.images.size()-1,terrain);
int neighbors = 0b000_000_000;
@@ -162,44 +183,40 @@ public class World implements Disposable, SaveFileContent {
int otherTerrain = getTerrainIndex(x + nx, y + ny);
if ((otherBiome & 1L << i) != 0 && biomeTerrain <= otherTerrain)
if ((otherBiome & 1L << i) != 0 && (biomeTerrain == otherTerrain) | biomeTerrain == 0)
neighbors |= (1 << bitIndex);
bitIndex--;
}
}
if(biomeTerrain!=0&&neighbors!=0b111_111_111)
{
bitIndex = 8;
int baseNeighbors=0;
if (biomeTerrain != 0 && neighbors != 0b111_111_111) {
bitIndex = 8;
int baseNeighbors = 0;
for (int ny = 1; ny > -2; ny--) {
for (int nx = -1; nx < 2; nx++) {
if ((getBiome(x + nx, y + ny) & (1L << i)) != 0 )
if ((getBiome(x + nx, y + ny) & (1L << i)) != 0)
baseNeighbors |= (1 << bitIndex);
bitIndex--;
}
}
information.add(new DrawingInformation(baseNeighbors,regions,0) );
information.add(new DrawingInformation(baseNeighbors, regions, 0));
}
information.add(new DrawingInformation(neighbors,regions,biomeTerrain) );
information.add(new DrawingInformation(neighbors, regions, biomeTerrain));
}
int lastFullNeighbour=-1;
int counter=0;
for(DrawingInformation info:information)
{
if(info.neighbors==0b111_111_111)
lastFullNeighbour= counter;
int lastFullNeighbour = -1;
int counter = 0;
for (DrawingInformation info : information) {
if (info.neighbors == 0b111_111_111)
lastFullNeighbour = counter;
counter++;
}
counter=0;
if(lastFullNeighbour<0&&information.size()!=0)
information.get(0).neighbors=0b111_111_111;
for(DrawingInformation info:information)
{
if(counter<lastFullNeighbour)
{
counter = 0;
if (lastFullNeighbour < 0 && information.size() != 0)
information.get(0).neighbors = 0b111_111_111;
for (DrawingInformation info : information) {
if (counter < lastFullNeighbour) {
counter++;
continue;
}
@@ -210,14 +227,34 @@ public class World implements Disposable, SaveFileContent {
}
public int getTerrainIndex(int x, int y) {
return terrainMap[x][height - y];
try {
return terrainMap[x][height - y - 1] & ~terrainMask;
} catch (ArrayIndexOutOfBoundsException e) {
return 0;
}
}
public boolean isStructure(int x, int y) {
try {
return (terrainMap[x][height - y - 1] & ~isStructureBit) != 0;
} catch (ArrayIndexOutOfBoundsException e) {
return false;
}
}
public long getBiome(int x, int y) {
try {
return biomeMap[x][height - y];
return biomeMap[x][height - y - 1];
} catch (ArrayIndexOutOfBoundsException e) {
return biomeMap[biomeMap.length-1][biomeMap[biomeMap.length-1].length-1];
return biomeMap[biomeMap.length - 1][biomeMap[biomeMap.length - 1].length - 1];
}
}
public boolean isColliding(int x, int y) {
try {
return (terrainMap[x][height - y - 1] & collisionBit) != 0;
} catch (ArrayIndexOutOfBoundsException e) {
return true;
}
}
@@ -225,10 +262,37 @@ public class World implements Disposable, SaveFileContent {
return data;
}
private void clearTerrain(int x, int y, int size) {
for (int xclear = -size; xclear < size; xclear++)
for (int yclear = -size; yclear < size; yclear++) {
try {
terrainMap[x + xclear][height - 1 - (y + yclear)] = 0;
} catch (ArrayIndexOutOfBoundsException e) {
}
}
}
private long measureGenerationTime(String msg, long lastTime) {
long currentTime = System.currentTimeMillis();
System.out.print("\n" + msg + " :\t\t" + ((currentTime - lastTime) / 1000f) + " s");
return currentTime;
}
public World generateNew(long seed) {
if (GuiBase.isAndroid())
GuiBase.getInterface().preventSystemSleep(true);
final long[] currentTime = {System.currentTimeMillis()};
long startTime = System.currentTimeMillis();
loadWorldData();
if(seed==0) { seed=random.nextLong(); }
this.seed=seed;
if (seed == 0) {
seed = random.nextLong();
}
this.seed = seed;
random.setSeed(seed);
OpenSimplexNoise noise = new OpenSimplexNoise(seed);
@@ -237,7 +301,7 @@ public class World implements Disposable, SaveFileContent {
height = data.height;
//save at all data
biomeMap = new long[width][height];
terrainMap= new int[width][height];
terrainMap = new int[width][height];
Pixmap pix = new Pixmap(width, height, Pixmap.Format.RGBA8888);
for (int x = 0; x < width; x++) {
@@ -250,257 +314,373 @@ public class World implements Disposable, SaveFileContent {
pix.setColor(1, 0, 0, 1);
pix.fill();
int biomeIndex = -1;
final int[] biomeIndex = {-1};
currentTime[0] = measureGenerationTime("loading data", currentTime[0]);
HashMap<BiomeStructureData, BiomeStructure> structureDataMap = new HashMap<>();
for (BiomeData biome : data.GetBiomes()) {
biomeIndex++;
int biomeXStart = (int) Math.round(biome.startPointX * (double) width);
int biomeYStart = (int) Math.round(biome.startPointY * (double) height);
int biomeWidth = (int) Math.round(biome.width * (double) width);
int biomeHeight = (int) Math.round(biome.height * (double) height);
int beginX = Math.max(biomeXStart - biomeWidth / 2, 0);
int beginY = Math.max(biomeYStart - biomeHeight / 2, 0);
int endX = Math.min(biomeXStart + biomeWidth, width);
int endY = Math.min(biomeYStart + biomeHeight, height);
if (biome.width == 1.0 && biome.height == 1.0) {
beginX = 0;
beginY = 0;
endX = width;
endY = height;
}
for (int x = beginX; x < endX; x++) {
for (int y = beginY; y < endY; y++) {
//value 0-1 based on noise
float noiseValue = ((float)noise.eval(x / (float) width * noiseZoom, y / (float) height * noiseZoom) + 1) / 2f;
noiseValue *= biome.noiseWeight;
//value 0-1 based on dist to origin
float distanceValue = ((float)Math.sqrt((x - biomeXStart) * (x - biomeXStart) + (y - biomeYStart) * (y - biomeYStart))) / (Math.max(biomeWidth, biomeHeight) / 2f);
distanceValue *= biome.distWeight;
if (noiseValue + distanceValue < 1.0 || biome.invertHeight && (1 - noiseValue) + distanceValue < 1.0) {
Color color = biome.GetColor();
float[] hsv = new float[3];
color.toHsv(hsv);
int count = (int) ((noiseValue - 0.5) * 10 / 4);
//hsv[2]+=(count*0.2);
color.fromHsv(hsv);
pix.setColor(color.r, color.g, color.b, 1);
pix.drawPixel(x, y);
biomeMap[x][y] |= (1L << biomeIndex);
int terrainCounter=1;
if(biome.terrain==null)
continue;
for(BiomeTerrainData terrain:biome.terrain)
{
float terrainNoise = ((float)noise.eval(x / (float) width * (noiseZoom*terrain.resolution), y / (float) height * (noiseZoom*terrain.resolution)) + 1) / 2;
if(terrainNoise>=terrain.min&&terrainNoise<=terrain.max)
{
terrainMap[x][y]=terrainCounter;
}
terrainCounter++;
}
}
if (biome.structures != null) {
int biomeWidth = (int) Math.round(biome.width * (double) width);
int biomeHeight = (int) Math.round(biome.height * (double) height);
for (BiomeStructureData data : biome.structures) {
long localSeed = seed;
ThreadUtil.getServicePool().submit(() -> {
long threadStartTime = System.currentTimeMillis();
BiomeStructure structure = new BiomeStructure(data, localSeed, biomeWidth, biomeHeight);
structure.initialize();
structureDataMap.put(data, structure);
measureGenerationTime("wavefunctioncollapse " + data.sourcePath, threadStartTime);
});
}
}
}
FThreads.invokeInEdtNowOrLater(() -> {
for (BiomeData biome : data.GetBiomes()) {
mapPoiIds = new PointOfInterestMap(getChunkSize(), data.tileSize, data.width / getChunkSize(),data.height / getChunkSize());
List<PointOfInterest> towns = new ArrayList<>();
List<Rectangle> otherPoints = new ArrayList<>();
otherPoints.add(new Rectangle(((float)data.width*data.playerStartPosX*(float)data.tileSize)-data.tileSize*3,((float)data.height*data.playerStartPosY*data.tileSize)-data.tileSize*3,data.tileSize*6,data.tileSize*6));
int biomeIndex2=-1;
for (BiomeData biome : data.GetBiomes()) {
biomeIndex2++;
for (PointOfInterestData poi : biome.getPointsOfInterest()) {
for (int i = 0; i < poi.count; i++) {
for (int counter = 0; counter < 500; counter++)//tries 100 times to find a free point
{
float radius = (float) Math.sqrt(((random.nextDouble())/2 * poi.radiusFactor));
float theta = (float) (random.nextDouble() * 2 * Math.PI);
float x = (float) (radius * Math.cos(theta));
x *= (biome.width * width / 2);
x += (biome.startPointX * width);
float y = (float) (radius * Math.sin(theta));
y *= (biome.height * height / 2);
y += (height - (biome.startPointY * height));
biomeIndex[0]++;
int biomeXStart = (int) Math.round(biome.startPointX * (double) width);
int biomeYStart = (int) Math.round(biome.startPointY * (double) height);
int biomeWidth = (int) Math.round(biome.width * (double) width);
int biomeHeight = (int) Math.round(biome.height * (double) height);
if((int)x<0||(int)y<=0||(int)y>=height||(int)x>=width|| biomeIndex2!= highestBiome(getBiome((int)x,(int)y)))
{
continue;
}
x*= data.tileSize;
y*= data.tileSize;
boolean breakNextLoop = false;
for (Rectangle rect : otherPoints) {
if (rect.contains(x, y)) {
breakNextLoop = true;
break;
int beginX = Math.max(biomeXStart - biomeWidth / 2, 0);
int beginY = Math.max(biomeYStart - biomeHeight / 2, 0);
int endX = Math.min(biomeXStart + biomeWidth / 2, width);
int endY = Math.min(biomeYStart + biomeHeight / 2, height);
if (biome.width == 1.0 && biome.height == 1.0) {
beginX = 0;
beginY = 0;
endX = width;
endY = height;
}
for (int x = beginX; x < endX; x++) {
for (int y = beginY; y < endY; y++) {
//value 0-1 based on noise
float noiseValue = ((float) noise.eval(x / (float) width * noiseZoom, y / (float) height * noiseZoom) + 1) / 2f;
noiseValue *= biome.noiseWeight;
//value 0-1 based on dist to origin
float distanceValue = ((float) Math.sqrt((x - biomeXStart) * (x - biomeXStart) + (y - biomeYStart) * (y - biomeYStart))) / (Math.max(biomeWidth, biomeHeight) / 2f);
distanceValue *= biome.distWeight;
if (noiseValue + distanceValue < 1.0 || biome.invertHeight && (1 - noiseValue) + distanceValue < 1.0) {
Color color = biome.GetColor();
float[] hsv = new float[3];
color.toHsv(hsv);
int count = (int) ((noiseValue - 0.5) * 10 / 4);
//hsv[2]+=(count*0.2);
color.fromHsv(hsv);
pix.setColor(color.r, color.g, color.b, 1);
pix.drawPixel(x, y);
biomeMap[x][y] |= (1L << biomeIndex[0]);
int terrainCounter = 1;
terrainMap[x][y] = 0;
if (biome.terrain != null) {
for (BiomeTerrainData terrain : biome.terrain) {
float terrainNoise = ((float) noise.eval(x / (float) width * (noiseZoom * terrain.resolution), y / (float) height * (noiseZoom * terrain.resolution)) + 1) / 2;
if (terrainNoise >= terrain.min && terrainNoise <= terrain.max) {
terrainMap[x][y] = terrainCounter;
}
terrainCounter++;
}
}
}
if (breakNextLoop)
{
boolean foundSolution=false;
boolean noSolution=false;
breakNextLoop=false;
for(int xi=-1;xi<2&&!foundSolution;xi++)
{
for(int yi=-1;yi<2&&!foundSolution;yi++)
{
for (Rectangle rect : otherPoints) {
if (rect.contains(x+xi*data.tileSize, y+yi*data.tileSize)) {
noSolution = true;
break;
if (biome.collision)
terrainMap[x][y] |= collisionBit;
if (biome.structures != null) {
for (BiomeStructureData data : biome.structures) {
while (!structureDataMap.containsKey(data)) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if(!noSolution)
{
foundSolution=true;
x=x+xi*data.tileSize;
y=y+yi*data.tileSize;
BiomeStructure structure = structureDataMap.get(data);
int structureXStart = x - (biomeXStart - biomeWidth / 2) - (int) ((data.x * biomeWidth) - (data.width * biomeWidth / 2));
int structureYStart = y - (biomeYStart - biomeHeight / 2) - (int) ((data.y * biomeHeight) - (data.height * biomeHeight / 2));
int structureIndex = structure.objectID(structureXStart, structureYStart);
if (structureIndex >= 0) {
pix.setColor(data.mappingInfo[structureIndex].getColor());
pix.drawPixel(x, y);
terrainMap[x][y] = terrainCounter + structureIndex;
if (structure.collision(structureXStart, structureYStart))
terrainMap[x][y] |= collisionBit;
terrainMap[x][y] |= isStructureBit;
}
terrainCounter += structure.structureObjectCount();
}
}
if(!foundSolution)
{
if(counter==499)
{
System.err.print("Can not place POI "+poi.name+"\n");
}
}
}
}
}
currentTime[0] = measureGenerationTime("biomes in total", currentTime[0]);
mapPoiIds = new PointOfInterestMap(getChunkSize(), data.tileSize, data.width / getChunkSize(), data.height / getChunkSize());
List<PointOfInterest> towns = new ArrayList<>();
List<PointOfInterest> notTowns = new ArrayList<>();
List<Rectangle> otherPoints = new ArrayList<>();
clearTerrain((int) (data.width * data.playerStartPosX), (int) (data.height * data.playerStartPosY), 10);
otherPoints.add(new Rectangle(((float) data.width * data.playerStartPosX * (float) data.tileSize) - data.tileSize * 3, ((float) data.height * data.playerStartPosY * data.tileSize) - data.tileSize * 3, data.tileSize * 6, data.tileSize * 6));
int biomeIndex2 = -1;
for (BiomeData biome : data.GetBiomes()) {
biomeIndex2++;
for (PointOfInterestData poi : biome.getPointsOfInterest()) {
for (int i = 0; i < poi.count; i++) {
for (int counter = 0; counter < 500; counter++)//tries 100 times to find a free point
{
float radius = (float) Math.sqrt(((random.nextDouble()) / 2 * poi.radiusFactor));
float theta = (float) (random.nextDouble() * 2 * Math.PI);
float x = (float) (radius * Math.cos(theta));
x *= (biome.width * width / 2);
x += (biome.startPointX * width);
float y = (float) (radius * Math.sin(theta));
y *= (biome.height * height / 2);
y += (height - (biome.startPointY * height));
if ((int) x < 0 || (int) y <= 0 || (int) y >= height || (int) x >= width || biomeIndex2 != highestBiome(getBiome((int) x, (int) y))) {
continue;
}
}
otherPoints.add(new Rectangle(x - data.tileSize * 4, y - data.tileSize * 4, data.tileSize * 8, data.tileSize * 8));
PointOfInterest newPoint = new PointOfInterest(poi, new Vector2(x, y), random);
mapPoiIds.add(newPoint);
x *= data.tileSize;
y *= data.tileSize;
Color color = biome.GetColor();
pix.setColor(color.r, 0.1f, 0.1f, 1);
pix.drawRectangle((int) x / data.tileSize - 3, height - (int) y / data.tileSize - 3, 6, 6);
if (poi.type!=null&&poi.type.equals("town")) {
towns.add(newPoint);
}
break;
}
}
}
}
//sort towns
List<Pair<PointOfInterest, PointOfInterest>> allSortedTowns = new ArrayList<>();//edge is first 32 bits id of first id and last 32 bits id of second
HashSet<Long> usedEdges=new HashSet<>();
for (int i = 0; i < towns.size() - 1; i++) {
PointOfInterest current = towns.get(i);
int smallestIndex = -1;
float smallestDistance = Float.MAX_VALUE;
for (int j = 0; j < towns.size(); j++) {
if(i==j||usedEdges.contains((long)i|((long)j<<32)))
continue;
float dist = current.getPosition().dst(towns.get(j).getPosition());
if (dist < smallestDistance) {
smallestDistance = dist;
smallestIndex = j;
}
}
if (smallestIndex < 0)
continue;
if(smallestDistance>data.maxRoadDistance)
continue;
usedEdges.add((long)i|((long)smallestIndex<<32));
usedEdges.add((long)i<<32|((long)smallestIndex));
allSortedTowns.add(Pair.of(current, towns.get(smallestIndex)));
}
biomeIndex++;
pix.setColor(1, 1, 1, 1);
for (Pair<PointOfInterest, PointOfInterest> townPair : allSortedTowns) {
Vector2 currentPoint = townPair.getKey().getTilePosition(data.tileSize);
Vector2 endPoint = townPair.getValue().getTilePosition(data.tileSize);
for (int x = (int) currentPoint.x - 1; x < currentPoint.x + 2; x++) {
for (int y = (int) currentPoint.y - 1; y < currentPoint.y + 2; y++) {
if(x<0||y<=0||x>=width||y>height)continue;
biomeMap[x][height - y] |= (1L << biomeIndex);
pix.drawPixel(x, height-y);
}
}
while (!currentPoint.equals(endPoint)) {
float xDir = endPoint.x - currentPoint.x;
float yDir = endPoint.y - currentPoint.y;
if (xDir == 0) {
if (yDir > 0)
currentPoint.y++;
else
currentPoint.y--;
} else if (yDir == 0) {
if (xDir > 0)
currentPoint.x++;
else
currentPoint.x--;
} else if (Math.abs(xDir) > Math.abs(yDir)) {
if (xDir > 0)
currentPoint.x++;
else
currentPoint.x--;
} else {
if (yDir > 0)
currentPoint.y++;
else
currentPoint.y--;
}
if( (int)currentPoint.x<0|| (int)currentPoint.y<=0|| (int)currentPoint.x>=width|| (int)currentPoint.y>height)continue;
biomeMap[(int) currentPoint.x][height - (int) currentPoint.y] |= (1L << biomeIndex);
pix.drawPixel((int) currentPoint.x, height - (int) currentPoint.y);
}
}
mapObjectIds = new SpritesDataMap(getChunkSize(), data.tileSize, data.width / getChunkSize());
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int invertedHeight = height - y - 1;
int currentBiome = highestBiome(biomeMap[x][invertedHeight]);
if (currentBiome >= data.GetBiomes().size())
continue;
BiomeData biome = data.GetBiomes().get(currentBiome);
for (String name : biome.spriteNames) {
BiomeSpriteData sprite = data.GetBiomeSprites().getSpriteData(name);
double spriteNoise = (noise.eval(x / (double) width * noiseZoom*sprite.resolution, y / (double) invertedHeight * noiseZoom*sprite.resolution) + 1) / 2;
if (spriteNoise >= sprite.startArea && spriteNoise <= sprite.endArea) {
if (random.nextFloat() <= sprite.density) {
String spriteKey = sprite.key();
int key;
if (!mapObjectIds.containsKey(spriteKey)) {
key = mapObjectIds.put(sprite.key(), sprite, data.GetBiomeSprites());
} else {
key = mapObjectIds.intKey(spriteKey);
boolean breakNextLoop = false;
for (Rectangle rect : otherPoints) {
if (rect.contains(x, y)) {
breakNextLoop = true;
break;
}
}
mapObjectIds.putPosition(key, new Vector2((float) x * data.tileSize + (random.nextFloat() * data.tileSize), (float) y * data.tileSize + (random.nextFloat() * data.tileSize)));
if (breakNextLoop) {
boolean foundSolution = false;
boolean noSolution = false;
breakNextLoop = false;
for (int xi = -1; xi < 2 && !foundSolution; xi++) {
for (int yi = -1; yi < 2 && !foundSolution; yi++) {
for (Rectangle rect : otherPoints) {
if (rect.contains(x + xi * data.tileSize, y + yi * data.tileSize)) {
noSolution = true;
break;
}
}
if (!noSolution) {
foundSolution = true;
x = x + xi * data.tileSize;
y = y + yi * data.tileSize;
}
}
}
if (!foundSolution) {
if (counter == 499) {
System.err.print("Can not place POI " + poi.name + "\n");
}
continue;
}
}
otherPoints.add(new Rectangle(x - data.tileSize * 4, y - data.tileSize * 4, data.tileSize * 8, data.tileSize * 8));
PointOfInterest newPoint = new PointOfInterest(poi, new Vector2(x, y), random);
clearTerrain((int) (x / data.tileSize), (int) (y / data.tileSize), 3);
mapPoiIds.add(newPoint);
Color color = biome.GetColor();
pix.setColor(color.r, 0.1f, 0.1f, 1);
pix.fillRectangle((int) x / data.tileSize - 3, height - (int) y / data.tileSize - 3, 6, 6);
if (poi.type != null && poi.type.equals("town")) {
towns.add(newPoint);
} else {
notTowns.add(newPoint);
}
break;
}
}
}
}
currentTime[0] = measureGenerationTime("poi placement", currentTime[0]);
//sort towns
List<Pair<PointOfInterest, PointOfInterest>> allSortedTowns = new ArrayList<>();
HashSet<Long> usedEdges = new HashSet<>();//edge is first 32 bits id of first id and last 32 bits id of second
for (int i = 0; i < towns.size() - 1; i++) {
PointOfInterest current = towns.get(i);
int smallestIndex = -1;
int secondSmallestIndex = -1;
float smallestDistance = Float.MAX_VALUE;
for (int j = 0; j < towns.size(); j++) {
if (i == j || usedEdges.contains((long) i | ((long) j << 32)))
continue;
float dist = current.getPosition().dst(towns.get(j).getPosition());
if (dist > data.maxRoadDistance)
continue;
if (dist < smallestDistance) {
smallestDistance = dist;
secondSmallestIndex = smallestIndex;
smallestIndex = j;
}
}
if (smallestIndex < 0)
continue;
usedEdges.add((long) i | ((long) smallestIndex << 32));
usedEdges.add((long) i << 32 | ((long) smallestIndex));
allSortedTowns.add(Pair.of(current, towns.get(smallestIndex)));
if (secondSmallestIndex < 0)
continue;
usedEdges.add((long) i | ((long) secondSmallestIndex << 32));
usedEdges.add((long) i << 32 | ((long) secondSmallestIndex));
//allSortedTowns.add(Pair.of(current, towns.get(secondSmallestIndex)));
}
List<Pair<PointOfInterest, PointOfInterest>> allPOIPathsToNextTown = new ArrayList<>();
for (int i = 0; i < notTowns.size() - 1; i++) {
PointOfInterest poi = notTowns.get(i);
int smallestIndex = -1;
float smallestDistance = Float.MAX_VALUE;
for (int j = 0; j < towns.size(); j++) {
float dist = poi.getPosition().dst(towns.get(j).getPosition());
if (dist < smallestDistance) {
smallestDistance = dist;
smallestIndex = j;
}
}
if (smallestIndex < 0)
continue;
allPOIPathsToNextTown.add(Pair.of(poi, towns.get(smallestIndex)));
}
biomeIndex[0]++;
pix.setColor(1, 1, 1, 1);
//reset terrain path to the next town
for (Pair<PointOfInterest, PointOfInterest> poiToTown : allPOIPathsToNextTown) {
int startX = (int) poiToTown.getKey().getTilePosition(data.tileSize).x;
int startY = (int) poiToTown.getKey().getTilePosition(data.tileSize).y;
int x1 = (int) poiToTown.getValue().getTilePosition(data.tileSize).x;
int y1 = (int) poiToTown.getValue().getTilePosition(data.tileSize).y;
int dx = Math.abs(x1 - startX);
int dy = Math.abs(y1 - startY);
int sx = startX < x1 ? 1 : -1;
int sy = startY < y1 ? 1 : -1;
int err = dx - dy;
int e2;
while (true) {
if (startX < 0 || startY <= 0 || startX >= width || startY > height) continue;
if ((terrainMap[startX][height - startY] & collisionBit) != 0)//clear terrain if it has collision
terrainMap[startX][height - startY] = 0;
pix.drawPixel(startX, height - startY);
if (startX == x1 && startY == y1)
break;
e2 = 2 * err;
if (e2 > -dy) {
err = err - dy;
startX = startX + sx;
} else if (e2 < dx) {
err = err + dx;
startY = startY + sy;
}
}
}
for (Pair<PointOfInterest, PointOfInterest> townPair : allSortedTowns) {
int startX = (int) townPair.getKey().getTilePosition(data.tileSize).x;
int startY = (int) townPair.getKey().getTilePosition(data.tileSize).y;
int x1 = (int) townPair.getValue().getTilePosition(data.tileSize).x;
int y1 = (int) townPair.getValue().getTilePosition(data.tileSize).y;
for (int x = startX - 1; x < startX + 2; x++) {
for (int y = startY - 1; y < startY + 2; y++) {
if (x < 0 || y <= 0 || x >= width || y > height) continue;
biomeMap[x][height - y - 1] |= (1L << biomeIndex[0]);
terrainMap[x][height - y - 1] = 0;
pix.drawPixel(x, height - y);
}
}
int dx = Math.abs(x1 - startX);
int dy = Math.abs(y1 - startY);
int sx = startX < x1 ? 1 : -1;
int sy = startY < y1 ? 1 : -1;
int err = dx - dy;
int e2;
while (true) {
if (startX < 0 || startY <= 0 || startX >= width || startY > height) continue;
biomeMap[startX][height - startY] |= (1L << biomeIndex[0]);
terrainMap[startX][height - startY] = 0;
pix.drawPixel(startX, height - startY);
if (startX == x1 && startY == y1)
break;
e2 = 2 * err;
if (e2 > -dy) {
err = err - dy;
startX = startX + sx;
} else if (e2 < dx) {
err = err + dx;
startY = startY + sy;
}
}
}
currentTime[0] = measureGenerationTime("roads", currentTime[0]);
mapObjectIds = new SpritesDataMap(getChunkSize(), data.tileSize, data.width / getChunkSize());
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int invertedHeight = height - y - 1;
int currentBiome = highestBiome(biomeMap[x][invertedHeight]);
if (currentBiome >= data.GetBiomes().size())
continue;//roads
if (isStructure(x, y))
continue;
BiomeData biome = data.GetBiomes().get(currentBiome);
for (String name : biome.spriteNames) {
BiomeSpriteData sprite = data.GetBiomeSprites().getSpriteData(name);
double spriteNoise = (noise.eval(x / (double) width * noiseZoom * sprite.resolution, y / (double) invertedHeight * noiseZoom * sprite.resolution) + 1) / 2;
if (spriteNoise >= sprite.startArea && spriteNoise <= sprite.endArea) {
if (random.nextFloat() <= sprite.density) {
String spriteKey = sprite.key();
int key;
if (!mapObjectIds.containsKey(spriteKey)) {
key = mapObjectIds.put(sprite.key(), sprite, data.GetBiomeSprites());
} else {
key = mapObjectIds.intKey(spriteKey);
}
mapObjectIds.putPosition(key, new Vector2((((float) x) + .25f + random.nextFloat() / 2) * data.tileSize, (((float) y + .25f) - random.nextFloat() / 2) * data.tileSize));
break;//only on sprite per point
}
}
}
}
}
}
biomeImage = pix;
biomeImage = pix;
measureGenerationTime("sprites", currentTime[0]);
});
System.out.print("\nGenerating world took :\t\t" + ((System.currentTimeMillis() - startTime) / 1000f) + " s\n");
WorldStage.getInstance().clearCache();
ThreadUtil.getServicePool().shutdownNow();
ThreadUtil.refreshServicePool();
if (GuiBase.isAndroid())
GuiBase.getInterface().preventSystemSleep(false);
return this;
}
@@ -549,10 +729,11 @@ public class World implements Disposable, SaveFileContent {
}
public PointOfInterest findPointsOfInterest(String name) {
return mapPoiIds.findPointsOfInterest(name);
return mapPoiIds.findPointsOfInterest(name);
}
public int getChunkSize() {
return (Scene.getIntendedWidth()>Scene.getIntendedHeight()?Scene.getIntendedWidth():Scene.getIntendedHeight()) / data.tileSize;
return (Scene.getIntendedWidth() > Scene.getIntendedHeight() ? Scene.getIntendedWidth() : Scene.getIntendedHeight()) / data.tileSize;
}
public void dispose() {
@@ -561,11 +742,11 @@ public class World implements Disposable, SaveFileContent {
}
public void setSeed(long seedOffset) {
random.setSeed(seedOffset+seed);
random.setSeed(seedOffset + seed);
}
public Texture getGlobalTexture() {
if(globalTexture == null){
if (globalTexture == null) {
globalTexture = new Texture(Config.instance().getFile("ui/sprite_markers.png"));
System.out.print("Loading auxiliary sprites.\n");
}

View File

@@ -21,51 +21,50 @@ import java.util.zip.InflaterInputStream;
/**
* Represents everything that will be saved, like the player and the world.
*/
public class WorldSave {
public class WorldSave {
static final public int AUTO_SAVE_SLOT =-1;
static final public int QUICK_SAVE_SLOT =-2;
static final public int INVALID_SAVE_SLOT =-3;
static final WorldSave currentSave=new WorldSave();
static final public int AUTO_SAVE_SLOT = -1;
static final public int QUICK_SAVE_SLOT = -2;
static final public int INVALID_SAVE_SLOT = -3;
static final WorldSave currentSave = new WorldSave();
public WorldSaveHeader header = new WorldSaveHeader();
private final AdventurePlayer player=new AdventurePlayer();
private final World world=new World();
private final PointOfInterestChanges.Map pointOfInterestChanges= new PointOfInterestChanges.Map();
private final AdventurePlayer player = new AdventurePlayer();
private final World world = new World();
private final PointOfInterestChanges.Map pointOfInterestChanges = new PointOfInterestChanges.Map();
private final SignalList onLoadList=new SignalList();
private final SignalList onLoadList = new SignalList();
public final World getWorld()
{
public final World getWorld() {
return world;
}
public AdventurePlayer getPlayer()
{
public AdventurePlayer getPlayer() {
return player;
}
public void onLoad(Runnable run)
{
public void onLoad(Runnable run) {
onLoadList.add(run);
}
public PointOfInterestChanges getPointOfInterestChanges(String id)
{
if(!pointOfInterestChanges.containsKey(id))
pointOfInterestChanges.put(id,new PointOfInterestChanges());
public PointOfInterestChanges getPointOfInterestChanges(String id) {
if (!pointOfInterestChanges.containsKey(id))
pointOfInterestChanges.put(id, new PointOfInterestChanges());
return pointOfInterestChanges.get(id);
}
static public boolean load(int currentSlot) {
String fileName = WorldSave.getSaveFile(currentSlot);
if (!new File(fileName).exists())
return false;
new File(getSaveDir()).mkdirs();
try {
try(FileInputStream fos = new FileInputStream(fileName);
InflaterInputStream inf = new InflaterInputStream(fos);
ObjectInputStream oos = new ObjectInputStream(inf))
{
try (FileInputStream fos = new FileInputStream(fileName);
InflaterInputStream inf = new InflaterInputStream(fos);
ObjectInputStream oos = new ObjectInputStream(inf)) {
currentSave.header = (WorldSaveHeader) oos.readObject();
SaveFileData mainData=(SaveFileData)oos.readObject();
SaveFileData mainData = (SaveFileData) oos.readObject();
currentSave.player.load(mainData.readSubData("player"));
GamePlayerUtil.getGuiPlayer().setName(currentSave.player.getName());
try {
@@ -87,9 +86,11 @@ public class WorldSave {
}
return true;
}
public static boolean isSafeFile(String name) {
return filenameToSlot(name)!= INVALID_SAVE_SLOT;
return filenameToSlot(name) != INVALID_SAVE_SLOT;
}
static public int filenameToSlot(String name) {
if (name.equals("auto_save.sav"))
return AUTO_SAVE_SLOT;
@@ -131,6 +132,7 @@ public class WorldSave {
identity = dp.getColorIdentityforAdventure();
} else {
starterDeck = isFantasy ? DeckgenUtil.getRandomOrPreconOrThemeDeck("", false, false, false) : Config.instance().starterDecks()[startingColorIdentity];
identity = DeckProxy.getColorIdentityforAdventure(starterDeck);
}
currentSave.player.create(name, startingColorIdentity, starterDeck, male, race, avatarIndex, isFantasy, diff);
currentSave.player.setWorldPosY((int) (currentSave.world.getData().playerStartPosY * currentSave.world.getData().height * currentSave.world.getTileSize()));
@@ -144,14 +146,17 @@ public class WorldSave {
}
public boolean autoSave() {
return save("auto save",AUTO_SAVE_SLOT);
return save("auto save", AUTO_SAVE_SLOT);
}
public boolean quickSave() {
return save("quick save",QUICK_SAVE_SLOT);
return save("quick save", QUICK_SAVE_SLOT);
}
public boolean quickLoad() {
return load(QUICK_SAVE_SLOT);
}
public boolean save(String text, int currentSlot) {
header.name = text;
@@ -159,17 +164,16 @@ public class WorldSave {
new File(getSaveDir()).mkdirs();
try {
try(FileOutputStream fos = new FileOutputStream(fileName);
DeflaterOutputStream def= new DeflaterOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(def))
{
header.saveDate= new Date();
try (FileOutputStream fos = new FileOutputStream(fileName);
DeflaterOutputStream def = new DeflaterOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(def)) {
header.saveDate = new Date();
oos.writeObject(header);
SaveFileData mainData=new SaveFileData();
mainData.store("player",currentSave.player.save());
mainData.store("world",currentSave.world.save());
SaveFileData mainData = new SaveFileData();
mainData.store("player", currentSave.player.save());
mainData.store("world", currentSave.world.save());
mainData.store("worldStage", WorldStage.getInstance().save());
mainData.store("pointOfInterestChanges",currentSave.pointOfInterestChanges.save());
mainData.store("pointOfInterestChanges", currentSave.pointOfInterestChanges.save());
oos.writeObject(mainData);
}

View File

@@ -42,7 +42,7 @@ public class Assets implements Disposable {
private ObjectMap<String, Texture> tmxMap;
private Texture defaultImage, dummy;
private TextureParameter textureParameter;
private int cGen = 0, cGenVal = 0, cFB = 0, cFBVal = 0, cTM, cTMVal = 0, cSF = 0, cSFVal = 0, cCF = 0, cCFVal = 0, aDF = 0, cDFVal = 0;
private int cGen = 0, cGenVal = 0, cFB = 0, cFBVal = 0, cTM = 0, cTMVal = 0, cSF = 0, cSFVal = 0, cCF = 0, cCFVal = 0, aDF = 0, cDFVal = 0;
public Assets() {
//init titlebg fallback
fallback_skins().put(0, new Texture(GuiBase.isAndroid()
@@ -55,14 +55,18 @@ public class Assets implements Disposable {
}
@Override
public void dispose() {
for (BitmapFont bitmapFont : counterFonts.values())
bitmapFont.dispose();
for (Texture texture : generatedCards.values())
texture.dispose();
for (Texture texture : fallback_skins.values())
texture.dispose();
for (Texture texture : tmxMap.values())
texture.dispose();
if (counterFonts != null)
for (BitmapFont bitmapFont : counterFonts.values())
bitmapFont.dispose();
if (generatedCards != null)
for (Texture texture : generatedCards.values())
texture.dispose();
if (fallback_skins != null)
for (Texture texture : fallback_skins.values())
texture.dispose();
if (tmxMap != null)
for (Texture texture : tmxMap.values())
texture.dispose();
if (defaultImage != null)
defaultImage.dispose();
if (dummy != null)

View File

@@ -293,10 +293,14 @@ public class ImageCache {
}
String fileName = file.getPath();
//load to assetmanager
if (!Forge.getAssets().manager().contains(fileName, Texture.class)) {
Forge.getAssets().manager().load(fileName, Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(fileName);
counter+=1;
try {
if (!Forge.getAssets().manager().contains(fileName, Texture.class)) {
Forge.getAssets().manager().load(fileName, Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(fileName);
counter += 1;
}
} catch (Exception e) {
System.err.println("Failed to load image: "+fileName);
}
//return loaded assets
@@ -305,7 +309,7 @@ public class ImageCache {
} else {
Texture cardTexture = Forge.getAssets().manager().get(fileName, Texture.class, false);
//if full bordermasking is enabled, update the border color
if (Forge.enableUIMask.equals("Full")) {
if (cardTexture != null && Forge.enableUIMask.equals("Full")) {
boolean borderless = isBorderless(imageKey);
updateBorders(cardTexture.toString(), borderless ? Pair.of(Color.valueOf("#171717").toString(), false): isCloserToWhite(getpixelColor(cardTexture)));
//if borderless, generate new texture from the asset and store
@@ -327,6 +331,7 @@ public class ImageCache {
syncQ.clear();
cardsLoaded.clear();
counter = 0;
CardRenderer.clearcardArtCache();
} catch (Exception e) {
//e.printStackTrace();
} finally {

View File

@@ -323,6 +323,8 @@ public abstract class VCardDisplayArea extends VDisplayArea implements ActivateH
@Override
public boolean tap(float x, float y, int count) {
if (count > 1) //prevent double choice lists or activate handle
return false;
if (renderedCardContains(x, y)) {
ThreadUtil.invokeInGameThread(new Runnable() { //must invoke in game thread in case a dialog needs to be shown
@Override

View File

@@ -67,6 +67,12 @@
<version>5.2.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.jetopto1.cling</groupId>
<artifactId>cling-core</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,5 +1,6 @@
{
"invertHeight": true,
"collision": true,
"name": "ocean",
"startPointX": 0.5,
"startPointY": 0.5,

View File

@@ -1,37 +1,145 @@
{
"startPointX": 0.70,
"startPointY": 0.78,
"name": "black",
"noiseWeight": 0.5,
"distWeight": 1.5,
"tilesetName":"Black",
"tilesetAtlas":"world/tilesets/terrain.atlas",
"terrain":[
{
"spriteName":"Black_1",
"min": 0,
"max": 0.2,
"resolution": 10
},{
"spriteName":"Black_2",
"min": 0.8,
"max": 1.0,
"resolution": 10
}
],
"width": 0.7,
"height": 0.7,
"color": "110903",
"spriteNames":[ "SwampTree","SwampTree2","DarkGras","Skull","SwampRock","DarkWood","Reed","Waterlily","Shroom","Shroom2"] ,
"enemies":[ "Beholder","Big Zombie","Black Wiz1","Black Wiz2","Black Wiz3","Dark Knight","Death Knight","Demon","Ghoul","Ghost","Harpy","Harpy 2","High Vampire","Lich","Rakdos Devil","Skeleton","Skeleton Soldier","Vampire","Zombie","Zombie Lord" ] ,
"pointsOfInterest":[
"Black Castle",
"Swamp Town","Swamp Town2",
"Zombie Town",
"Graveyard", "Graveyard1", "Graveyard2", "Graveyard3", "Graveyard4",
"VampireCastle", "VampireCastle1", "VampireCastle2",
"EvilGrove", "EvilGrove1", "EvilGrove2", "EvilGrove3", "EvilGrove4",
"SkullCaveB", "SkullCaveB1", "SkullCaveB2",
"CaveB", "CaveB1", "CaveB2", "CaveB3", "CaveB4", "CaveB5", "CaveB6", "CaveB8", "CaveBA"
]
"startPointX": 0.7,
"startPointY": 0.78,
"noiseWeight": 0.5,
"distWeight": 1.5,
"name": "black",
"tilesetAtlas": "world/tilesets/terrain.atlas",
"tilesetName": "Black",
"terrain": [
{
"spriteName": "Black_1",
"max": 0.2,
"resolution": 10
},
{
"spriteName": "Black_2",
"min": 0.8,
"max": 1,
"resolution": 10
}
],
"width": 0.7,
"height": 0.7,
"color": "110903",
"spriteNames": [
"SwampTree",
"SwampTree2",
"DarkGras",
"Skull",
"SwampRock",
"DarkWood",
"Reed",
"Waterlily",
"Shroom",
"Shroom2"
],
"enemies": [
"Beholder",
"Big Zombie",
"Black Wiz1",
"Black Wiz2",
"Black Wiz3",
"Dark Knight",
"Death Knight",
"Demon",
"Ghoul",
"Ghost",
"Harpy",
"Harpy 2",
"High Vampire",
"Lich",
"Rakdos Devil",
"Skeleton",
"Skeleton Soldier",
"Vampire",
"Zombie",
"Zombie Lord"
],
"pointsOfInterest": [
"Black Castle",
"Swamp Town",
"Swamp Town2",
"Zombie Town",
"Graveyard",
"Graveyard1",
"Graveyard2",
"Graveyard3",
"Graveyard4",
"VampireCastle",
"VampireCastle1",
"VampireCastle2",
"EvilGrove",
"EvilGrove1",
"EvilGrove2",
"EvilGrove3",
"EvilGrove4",
"SkullCaveB",
"SkullCaveB1",
"SkullCaveB2",
"CaveB",
"CaveB1",
"CaveB2",
"CaveB3",
"CaveB4",
"CaveB5",
"CaveB6",
"CaveB8",
"CaveBA"
],
"structures": [
{
"N": 2,
"x": 0.5,
"y": 0.5,
"structureAtlasPath": "world/tilesets/structures.atlas",
"sourcePath": "world/tilesets/swamp_forest.png",
"maskPath": "world/tilesets/ring.png",
"height": 0.5,
"width": 0.5,
"symmetry": 8,
"periodicOutput": false,
"mappingInfo": [
{
"name": "swamp_forest",
"color": "007000",
"collision": true
},
{
"name": "swamp_water",
"color": "005050",
"collision": true
}
]
},
{
"N": 2,
"x": 0.5,
"y": 0.5,
"structureAtlasPath": "world/tilesets/structures.atlas",
"sourcePath": "world/tilesets/swamp_ruins.png",
"maskPath": "world/tilesets/circle.png",
"height": 0.20000002,
"width": 0.20000002,
"symmetry": 1,
"periodicOutput": false,
"mappingInfo": [
{
"name": "deep_swamp",
"color": "002000",
"collision": true
},
{
"name": "structure",
"color": "505050",
"collision": true
},
{
"name": "swamp_forest2",
"color": "007000",
"collision": true
}
]
}
]
}

View File

@@ -1,38 +1,126 @@
{
"startPointX": 0.79,
"startPointY": 0.43,
"name": "blue",
"noiseWeight": 0.5,
"distWeight": 1.5,
"tilesetName":"Blue",
"tilesetAtlas":"world/tilesets/terrain.atlas",
"terrain":[
{
"spriteName":"Blue_1",
"min": 0,
"max": 0.2,
"resolution": 10
}, {
"spriteName":"Blue_2",
"min": 0.8,
"max": 1.0,
"resolution": 10
}
],
"width": 0.7,
"height": 0.7,
"color": "10a2e0",
"spriteNames":["IslandTree" ,"Coral" ,"Shell" ],
"enemies":[ "Bird","Djinn","Elemental","Merfolk","Merfolk Avatar","Merfolk Fighter","Merfolk Lord","Merfolk Soldier","Merfolk warrior","Blue Wiz1","Blue Wiz2","Blue Wiz3","Geist","Rogue","Sea Monster","Tarkir Djinn","Doppelganger" ] ,
"pointsOfInterest":[
"Blue Castle",
"Island Town",
"NestU",
"MerfolkPool", "MerfolkPool1", "MerfolkPool2", "MerfolkPool3", "MerfolkPool4",
"DjinnPalace", "DjinnPalace1",
"Factory", "Factory1",
"MageTowerX",
"MageTowerU", "MageTowerU1", "MageTowerU2", "MageTowerU3", "MageTowerU4", "MageTowerU5", "MageTowerU6", "MageTowerU7", "MageTowerUD",
"CaveU", "CaveU1", "CaveU2", "CaveU3", "CaveU4"
]
"startPointX": 0.79,
"startPointY": 0.43,
"noiseWeight": 0.5,
"distWeight": 1.5,
"name": "blue",
"tilesetAtlas": "world/tilesets/terrain.atlas",
"tilesetName": "Blue",
"terrain": [
{
"spriteName": "Blue_1",
"max": 0.2,
"resolution": 10
},
{
"spriteName": "Blue_2",
"min": 0.8,
"max": 1,
"resolution": 10
}
],
"width": 0.7,
"height": 0.7,
"color": "10a2e0",
"spriteNames": [
"IslandTree",
"Coral",
"Shell"
],
"enemies": [
"Bird",
"Djinn",
"Elemental",
"Merfolk",
"Merfolk Avatar",
"Merfolk Fighter",
"Merfolk Lord",
"Merfolk Soldier",
"Merfolk warrior",
"Blue Wiz1",
"Blue Wiz2",
"Blue Wiz3",
"Geist",
"Rogue",
"Sea Monster",
"Tarkir Djinn",
"Doppelganger"
],
"pointsOfInterest": [
"Blue Castle",
"Island Town",
"NestU",
"MerfolkPool",
"MerfolkPool1",
"MerfolkPool2",
"MerfolkPool3",
"MerfolkPool4",
"DjinnPalace",
"DjinnPalace1",
"Factory",
"Factory1",
"MageTowerX",
"MageTowerU",
"MageTowerU1",
"MageTowerU2",
"MageTowerU3",
"MageTowerU4",
"MageTowerU5",
"MageTowerU6",
"MageTowerU7",
"MageTowerUD",
"CaveU",
"CaveU1",
"CaveU2",
"CaveU3",
"CaveU4"
],
"structures": [
{
"x": 0.5,
"y": 0.5,
"structureAtlasPath": "world/tilesets/structures.atlas",
"sourcePath": "world/tilesets/water.png",
"maskPath": "world/tilesets/circle.png",
"height": 0.20000002,
"width": 0.20000002,
"symmetry": 8,
"periodicOutput": false,
"mappingInfo": [
{
"name": "water",
"color": "0070a0",
"collision": true
},
{
"name": "island_forest",
"color": "00a000",
"collision": true
}
]
},
{
"x": 0.5,
"y": 0.5,
"structureAtlasPath": "world/tilesets/structures.atlas",
"sourcePath": "world/tilesets/island_forest.png",
"maskPath": "world/tilesets/ring.png",
"height": 0.5,
"width": 0.5,
"symmetry": 8,
"periodicOutput": false,
"mappingInfo": [
{
"name": "water",
"color": "0070a0",
"collision": true
},
{
"name": "island_forest",
"color": "00a000",
"collision": true
}
]
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,36 +1,135 @@
{
"startPointX": 0.22,
"startPointY": 0.43,
"name": "green",
"noiseWeight": 0.5,
"distWeight": 1.5,
"tilesetName":"Green",
"tilesetAtlas":"world/tilesets/terrain.atlas",
"terrain":[
{
"spriteName":"Green_1",
"min": 0,
"max": 0.2,
"resolution": 10
},{
"spriteName":"Green_2",
"min": 0.8,
"max": 1.0,
"resolution": 10
}
],
"width": 0.7,
"height": 0.7,
"color": "59a650",
"spriteNames":[ "WoodTree","WoodTree2","Bush","Stump","Moss","Stone","Flower","Wood"] ,
"enemies":[ "Ape","Bear","Centaur","Centaur Warrior","Dino","Eldraine Faerie","Elf","Elf warrior","Elk","Faerie","Giant Spider","Gorgon","Gorgon 2","Green Beast","Green Wiz1","Green Wiz2","Green Wiz3","High Elf","Hydra","Satyr","Snake","Spider","Treefolk","Treefolk Guardian","Viper","Werewolf","Wurm" ] ,
"pointsOfInterest":[
"Green Castle",
"Forest Town",
"ElfTown",
"WurmPond",
"Grove", "Grove1", "Grove2", "Grove3", "Grove4", "Grove5", "Grove6", "Grove7", "Grove8",
"CatLairG", "CatLairG1", "CatLairG2",
"CaveG", "CaveG1", "CaveG2", "CaveG3", "CaveG4", "CaveG5", "CaveG6", "CaveG8", "CaveG9", "CaveGB"
]
{
"startPointX": 0.22,
"startPointY": 0.43,
"noiseWeight": 0.5,
"distWeight": 1.5,
"name": "green",
"tilesetAtlas": "world/tilesets/terrain.atlas",
"tilesetName": "Green",
"terrain": [
{
"spriteName": "Green_1",
"max": 0.2,
"resolution": 10
},
{
"spriteName": "Green_2",
"min": 0.8,
"max": 1,
"resolution": 10
}
],
"width": 0.7,
"height": 0.7,
"color": "59a650",
"spriteNames": [
"WoodTree",
"WoodTree2",
"Bush",
"Stump",
"Moss",
"Stone",
"Flower",
"Wood"
],
"enemies": [
"Ape",
"Bear",
"Centaur",
"Centaur Warrior",
"Dino",
"Eldraine Faerie",
"Elf",
"Elf warrior",
"Elk",
"Faerie",
"Giant Spider",
"Gorgon",
"Gorgon 2",
"Green Beast",
"Green Wiz1",
"Green Wiz2",
"Green Wiz3",
"High Elf",
"Hydra",
"Satyr",
"Snake",
"Spider",
"Treefolk",
"Treefolk Guardian",
"Viper",
"Werewolf",
"Wurm"
],
"pointsOfInterest": [
"Green Castle",
"Forest Town",
"ElfTown",
"WurmPond",
"Grove",
"Grove1",
"Grove2",
"Grove3",
"Grove4",
"Grove5",
"Grove6",
"Grove7",
"Grove8",
"CatLairG",
"CatLairG1",
"CatLairG2",
"CaveG",
"CaveG1",
"CaveG2",
"CaveG3",
"CaveG4",
"CaveG5",
"CaveG6",
"CaveG8",
"CaveG9",
"CaveGB"
],
"structures": [
{
"N": 2,
"x": 0.5,
"y": 0.5,
"structureAtlasPath": "world/tilesets/structures.atlas",
"sourcePath": "world/tilesets/forest.png",
"maskPath": "world/tilesets/circle.png",
"height": 0.20000002,
"width": 0.20000002,
"symmetry": 1,
"mappingInfo": [
{
"name": "forest",
"color": "007000",
"collision": true
}
]
},
{
"N": 2,
"x": 0.5,
"y": 0.5,
"structureAtlasPath": "world/tilesets/structures.atlas",
"sourcePath": "world/tilesets/lake.png",
"maskPath": "world/tilesets/ring.png",
"height": 0.5,
"width": 0.5,
"periodicOutput": false,
"mappingInfo": [
{
"name": "lake",
"color": "0070a0",
"collision": true
},
{
"name": "forest2",
"color": "009000",
"collision": true
}
]
}
]
}

View File

@@ -1,39 +1,144 @@
{
"startPointX": 0.31,
"startPointY": 0.78,
"name": "red",
"noiseWeight": 0.5,
"distWeight": 1.5,
"tilesetName":"Red",
"tilesetAtlas":"world/tilesets/terrain.atlas",
"terrain":[
{
"spriteName":"Red_1",
"min": 0,
"max": 0.2,
"resolution": 10
},{
"spriteName":"Red_2",
"min": 0.8,
"max": 1.0,
"resolution": 10
}
],
"width": 0.7,
"height": 0.7,
"color": "b63729",
"spriteNames":[ "MountainTree","MountainTree2","MountainRock","LargeMountainRock","Gravel"] ,
"enemies":[ "Amonkhet Minotaur","Ashmouth Devil","Axgard Dwarf","Berserker","Boggart","Cyclops","Devil","Dinosaur","Dragon","Dwarf","Efreet","Fire Elemental","Flame Elemental","Goblin","Goblin Chief","Goblin Warrior","Hellhound","Immersturm Demon","Khan","Minotaur","Minotaur Flayer","Red Beast","Red Wiz1","Red Wiz2","Red Wiz3","Shaman","Troll","Vampire Lord","Viashino","Yeti" ] ,
"pointsOfInterest":[
"Red Castle",
"Mountain Town",
"YuleTown",
"BarbarianCamp", "BarbarianCamp1", "BarbarianCamp2",
"Maze", "Maze1", "Maze2", "Maze3",
"Fort", "Fort5",
"Factory", "Factory2", "Factory3",
"SnowAbbey", "SnowAbbey1", "SnowAbbey2",
"SkullCaveR", "SkullCaveR1", "SkullCaveR2",
"CaveR", "CaveR1", "CaveR2", "CaveR3", "CaveR4", "CaveR5", "CaveR6", "CaveR7", "CaveR8", "CaveR9", "CaveRA", "CaveRB", "CaveRC", "CaveRE", "CaveRG", "CaveRH", "CaveRJ"
]
"startPointX": 0.31,
"startPointY": 0.78,
"noiseWeight": 0.5,
"distWeight": 1.5,
"name": "red",
"tilesetAtlas": "world/tilesets/terrain.atlas",
"tilesetName": "Red",
"terrain": [
{
"spriteName": "Red_1",
"max": 0.2,
"resolution": 10
},
{
"spriteName": "Red_2",
"min": 0.8,
"max": 1,
"resolution": 10
}
],
"width": 0.7,
"height": 0.7,
"color": "b63729",
"spriteNames": [
"MountainTree",
"MountainTree2",
"MountainRock",
"Gravel"
],
"enemies": [
"Amonkhet Minotaur",
"Ashmouth Devil",
"Axgard Dwarf",
"Berserker",
"Boggart",
"Cyclops",
"Devil",
"Dinosaur",
"Dragon",
"Dwarf",
"Efreet",
"Fire Elemental",
"Flame Elemental",
"Goblin",
"Goblin Chief",
"Goblin Warrior",
"Hellhound",
"Immersturm Demon",
"Khan",
"Minotaur",
"Minotaur Flayer",
"Red Beast",
"Red Wiz1",
"Red Wiz2",
"Red Wiz3",
"Shaman",
"Troll",
"Vampire Lord",
"Viashino",
"Yeti"
],
"pointsOfInterest": [
"Red Castle",
"Mountain Town",
"YuleTown",
"BarbarianCamp",
"BarbarianCamp1",
"BarbarianCamp2",
"Maze",
"Maze1",
"Maze2",
"Maze3",
"Fort",
"Fort5",
"Factory",
"Factory2",
"Factory3",
"SnowAbbey",
"SnowAbbey1",
"SnowAbbey2",
"SkullCaveR",
"SkullCaveR1",
"SkullCaveR2",
"CaveR",
"CaveR1",
"CaveR2",
"CaveR3",
"CaveR4",
"CaveR5",
"CaveR6",
"CaveR7",
"CaveR8",
"CaveR9",
"CaveRA",
"CaveRB",
"CaveRC",
"CaveRE",
"CaveRG",
"CaveRH",
"CaveRJ"
],
"structures": [
{
"N": 2,
"x": 0.5,
"y": 0.5,
"structureAtlasPath": "world/tilesets/structures.atlas",
"sourcePath": "world/tilesets/mountain.png",
"maskPath": "world/tilesets/ring.png",
"height": 0.5,
"width": 0.5,
"periodicOutput": false,
"mappingInfo": [
{
"name": "mountain",
"color": "a07020",
"collision": true
},
{
"name": "mountain_forest",
"color": "007000",
"collision": true
}
]
},
{
"x": 0.5,
"y": 0.5,
"structureAtlasPath": "world/tilesets/structures.atlas",
"sourcePath": "world/tilesets/lava.png",
"maskPath": "world/tilesets/circle.png",
"height": 0.2,
"width": 0.2,
"mappingInfo": [
{
"name": "lava",
"color": "ff5000",
"collision": true
}
]
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,20 @@
forest.png
size: 96,64
format: RGBA8888
filter: Nearest,Nearest
repeat: none
Source
rotate: false
xy: 0, 0
size: 16, 16
orig: 0, 0
offset: 0, 0
index: 0
structure_000000
rotate: false
xy: 48, 0
size: 48, 64
orig: 0, 0
offset: 0, 0
index: 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,60 @@
structures.png
size: 288,384
format: RGBA8888
filter: Nearest,Nearest
repeat: none
forest
xy: 0, 0
size: 48, 64
lake
xy: 48, 0
size: 48, 64
forest2
xy: 96, 0
size: 48, 64
swamp_forest
xy: 0, 64
size: 48, 64
swamp_forest2
xy: 48, 64
size: 48, 64
structure
xy: 96, 64
size: 48, 64
swamp_water
xy: 144, 64
size: 48, 64
deep_swamp
xy: 192, 64
size: 48, 64
mountain
xy: 0, 128
size: 48, 64
lava
xy: 48, 128
size: 48, 64
mountain_forest
xy: 96, 128
size: 48, 64
plateau
xy: 0, 192
size: 48, 64
plains_forest
xy: 48, 192
size: 48, 64
water
xy: 0, 256
size: 48, 64
island_forest
xy: 48, 256
size: 48, 64
hole
xy: 0, 320
size: 48, 64
waste_mountain
xy: 48, 320
size: 48, 64
waste_structure
xy: 96, 320
size: 48, 64

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