package com.shade.entities.mushroom; import java.util.LinkedList; import java.util.Queue; import org.newdawn.slick.geom.Shape; import org.newdawn.slick.GameContainer; import org.newdawn.slick.SlickException; import com.crash.Body; import com.shade.entities.Basket; import com.shade.util.Geom; public class MushroomFactory { /** * Corresponds to the Mushroom.Type enum. */ private static final double[] distribution = { 0, .9, 0, .1 }; private static final double PROPENSITY = .002; private static final float BASKET_THRESHOLD = 10000; private static final float GOLD_BASKET_THRESHOLD = 20000; private static final int GOLD_RATIO_INVERSE =10; /* Minimum number of mushrooms alive at any one time. */ private int floor; private double propensity; /* * List of existing mushrooms. Mushrooms should remove themselves when * removed from the level. */ private LinkedList<Mushroom> mushrooms; /* * queue of upcoming mushroom types */ private Queue<Integer> upcomingType; /** * @param floor * The baseline number of mushrooms on the field. * @param propensity * The likelihood to add a mushroom over the baseline. */ public MushroomFactory(int floor) { this.floor = floor; this.propensity = PROPENSITY; mushrooms = new LinkedList<Mushroom>(); upcomingType = new LinkedList<Integer>(); } /** * Return true you should create a new mushroom. * * @return */ public boolean active() { if (mushrooms.size() < floor) { return true; } return (Math.random() <= propensity); } public Mushroom getMushroom(GameContainer c, Shape shadow, Body b) throws SlickException { try { float x = randomX(c, shadow); float y = randomY(c, shadow); int t = nextType();//randomType(); switch (t) { case 3: if (x == -1 || y == -1 || Geom.distance2(x, y, b.getXCenter(), b.getYCenter()) < GOLD_BASKET_THRESHOLD) { return null; } break; default: if (x == -1 || y == -1 || Geom.distance2(x, y, b.getXCenter(), b.getYCenter()) < BASKET_THRESHOLD) { return null; } } Mushroom m = new Mushroom(x, y, getType(t), this); mushrooms.add(m); return m; } catch (MushroomFactoryException e) { throw new SlickException(e.getMessage()); } } private float randomX(GameContainer c, Shape s) throws MushroomFactoryException { float x = -1; int numTries = 0; while ((x < 0 || x >= c.getWidth()) && numTries < 6) { x = (float) (s.getMaxX() - s.getMinX() * Math.random() * 0.66); x += s.getX(); numTries++; if (numTries > 6) { throw new MushroomFactoryException("Can't find valid point."); } } return (numTries < 6) ? x : -1; } private float randomY(GameContainer c, Shape s) throws MushroomFactoryException { float y = -1; int numTries = 0; while ((y < 0 || y >= c.getHeight()) && numTries < 6) { y = (float) (s.getMaxY() - s.getMinY() * Math.random() * 0.66); y += s.getY(); numTries++; if (numTries > 6) { throw new MushroomFactoryException("Can't find valid point."); } } return (numTries < 6) ? y : -1; } public void remove(Mushroom m) { mushrooms.remove(m); } private Mushroom.Types getType(int i) { Mushroom.Types[] types = Mushroom.Types.values(); return types[i]; } /** * Statistically based technique for generating mushrooms. ARGH ALEX LERN * SUM MATH K? * * @return */ private int nextType(){ if(upcomingType.size()<1){ //generate list int[] types = new int[GOLD_RATIO_INVERSE]; int goldIndex = (int)(Math.random()*GOLD_RATIO_INVERSE); for(int i =0;i<GOLD_RATIO_INVERSE;i++){ types[i] = 1; if(i==goldIndex)types[i]=3; upcomingType.add(types[i]); } } return upcomingType.peek(); } public void noteSpawn(){ upcomingType.poll(); } private int randomType() { double r = Math.random(); double max = 0; for (int i = 0; i < distribution.length; i++) { max += distribution[i]; if (r <= max) return i; } return 0; // should never reach here } @SuppressWarnings("serial") private class MushroomFactoryException extends Exception { public MushroomFactoryException(String message) { super(message); } } }