A boring overland world was generated from a grammar!
This commit is contained in:
@@ -7,6 +7,8 @@ import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import dk.itu.mario.level.LevelComponent.TYPE;
|
||||
|
||||
|
||||
public class LevelGrammar {
|
||||
private Variable start;
|
||||
@@ -45,6 +47,24 @@ public class LevelGrammar {
|
||||
return generateRandom(new Random().nextLong());
|
||||
}
|
||||
|
||||
//TODO: refactor to recursively add children to the current node based on production rule
|
||||
public LevelParseTree generateRandomTree(long randomSeed, int width) {
|
||||
System.out.println("Generating random level parameters using seed: "
|
||||
+ randomSeed);
|
||||
List<Variable> startRuleRHS = getRule(getStart()).getRHS();
|
||||
|
||||
ParseNode rootNode = new ParseNode(TYPE.FLAT,1.0);
|
||||
LevelParseTree parseTree = new LevelParseTree(rootNode, 0, width);
|
||||
|
||||
for (Variable var : startRuleRHS) {
|
||||
if (var.isTerminal()) {
|
||||
rootNode.addChild(new ParseNode(TYPE.FLAT,0.5));
|
||||
}
|
||||
}
|
||||
|
||||
return parseTree;
|
||||
}
|
||||
|
||||
public ProductionRule getRule(Variable var) {
|
||||
return ruleMap.get(var);
|
||||
}
|
||||
|
||||
52
src/dk/itu/mario/level/grammar/LevelParseTree.java
Normal file
52
src/dk/itu/mario/level/grammar/LevelParseTree.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package dk.itu.mario.level.grammar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dk.itu.mario.level.LevelComponent;
|
||||
|
||||
public class LevelParseTree {
|
||||
private ParseNode root;
|
||||
private int start;
|
||||
private int width;
|
||||
|
||||
public LevelParseTree(ParseNode root, int start, int width) {
|
||||
this.root = root;
|
||||
this.start = start;
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public List<LevelComponent> getLevelTemplate() {
|
||||
List<LevelComponent> levelCompList = new ArrayList<LevelComponent>();
|
||||
getComponents(root,start,width, levelCompList);
|
||||
return levelCompList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerate the leaf nodes (level components) in depth-first order.
|
||||
* @param node
|
||||
* @param start
|
||||
* @param end
|
||||
*/
|
||||
private void getComponents(ParseNode node, int start, int end, List<LevelComponent> levelCompList) {
|
||||
int numChildren = node.getNumChildren();
|
||||
if (numChildren == 0) {
|
||||
LevelComponent.TYPE lcType = node.getType();
|
||||
levelCompList.add(new LevelComponent(lcType, start, end));
|
||||
} else {
|
||||
int width = end - start;
|
||||
int childOffset = 0;
|
||||
for (int childIndex = 0; childIndex < numChildren; childIndex++) {
|
||||
ParseNode childNode = node.getChild(childIndex);
|
||||
int childStart = start + childOffset;
|
||||
int childWidth = (int)(width * childNode.getPercentLength());
|
||||
if (childIndex > 0) {
|
||||
getComponents(childNode,childStart+1,childStart + childWidth,levelCompList);
|
||||
} else { // don't offset by 1 if this is the first child component.
|
||||
getComponents(childNode,childStart,childStart + childWidth,levelCompList);
|
||||
}
|
||||
childOffset += childWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
62
src/dk/itu/mario/level/grammar/ParseNode.java
Normal file
62
src/dk/itu/mario/level/grammar/ParseNode.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package dk.itu.mario.level.grammar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dk.itu.mario.level.LevelComponent;
|
||||
|
||||
public class ParseNode {
|
||||
private LevelComponent.TYPE levelCompType;
|
||||
private double percentLength;
|
||||
private List<ParseNode> children = new ArrayList<ParseNode>();
|
||||
|
||||
public ParseNode(LevelComponent.TYPE levelCompType, double percentLength) {
|
||||
this.levelCompType = levelCompType;
|
||||
this.percentLength = percentLength;
|
||||
}
|
||||
|
||||
public void addChild(ParseNode child) {
|
||||
children.add(child);
|
||||
}
|
||||
|
||||
public LevelComponent.TYPE getType() {
|
||||
return levelCompType;
|
||||
}
|
||||
|
||||
public ParseNode getChild(int index) {
|
||||
return children.get(index);
|
||||
}
|
||||
|
||||
public int getNumChildren() {
|
||||
return children.size();
|
||||
}
|
||||
|
||||
public double getPercentLength() {
|
||||
return percentLength;
|
||||
}
|
||||
|
||||
public void setChildLengthRatios(double... childPercentLengths) {
|
||||
double sumLength = 0.0;
|
||||
for (double cpl : childPercentLengths) {
|
||||
sumLength += cpl;
|
||||
}
|
||||
if (childPercentLengths.length != children.size()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Error - number of requested child percent lengths to set does not match the number of children: "
|
||||
+ childPercentLengths.length
|
||||
+ " != "
|
||||
+ children.size());
|
||||
}
|
||||
if (Math.abs(sumLength - 1.0) > 0.01) {
|
||||
throw new IllegalArgumentException(
|
||||
"Error - requested child percent lengths do not sum to 100% within an error of 1%.");
|
||||
}
|
||||
for (int i = 0; i < childPercentLengths.length; i++) {
|
||||
children.get(i).setPercentLength(childPercentLengths[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPercentLength(double percentLength) {
|
||||
this.percentLength = percentLength;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user