// HexaPacman.java
package app.hexapacman;
import java.util.LinkedList;
import ch.aplu.android.*;
import ch.aplu.android.PointD;
import android.graphics.Point;
import android.graphics.Color;
public class HexaPacman extends GameGrid implements GGActorCollisionListener
{
private GGStatusBar status;
private Pacman hexaPacman;
private GGPanel p;
private LinkedList<Jewel> availableJewels = new LinkedList<Jewel>();
private LinkedList<Jewel> allJewels = new LinkedList<Jewel>();
private HealthPointBar hpBar;
private int score;
private final int initialHealth = 50;
public HexaPacman()
{
super(WHITE, windowZoom(700));
status = addStatusBar(30);
}
public void main()
{
getBg().clear(WHITE);
p = getPanel(-10, 10, 0.5);
p.setAutoRefreshEnabled(false);
hexaPacman = new Pacman(p);
PointD hexagonSpawnPoint = new PointD(0, 0);
addActorNoRefresh(hexaPacman, toLocation(p.toPixelPoint(hexagonSpawnPoint)));
for (int i = 1; i < 10; i++)
{
Jewel j = new Jewel(availableJewels);
allJewels.add(j);
//jewel is added to the jewels list in reset() when added to gamegrid
addActorNoRefresh(j, new Location(-100, -100)); //out of sight
hexaPacman.addCollisionActor(j);
}
hexaPacman.addActorCollisionListener(this);
setSimulationPeriod(30);
setPaintOrder(HexaPacman.class, Jewel.class);
addMultiTouchListener(hexaPacman, GGMultiTouch.press | GGMultiTouch.pointerPress | GGMultiTouch.release);
hpBar = new HealthPointBar(p, initialHealth);
status.setText("Tap the screen to the right/left to turn Hexa-Pacman!");
doRun();
}
public void act()
{
if (hpBar.isGameOver())
{
doPause();
showToast("Game Over, tap screen to reset");
// ugly way to prevent immediate restart
setTouchEnabled(false);
delay(1000);
setTouchEnabled(true);
}
launchJewel();
}
private void launchJewel()
{
if (!availableJewels.isEmpty() && Math.random() < 0.05)
{
GGVector v = new GGVector(10, 10);
v.rotate(Math.random() * Math.PI * 2);
PointD spawnPoint = new PointD(v);
Actor spawningJewel = availableJewels.poll();
spawningJewel.setLocation(toLocation(p.toPixelPoint(spawnPoint)));
spawningJewel.setDirection(spawningJewel.getLocation().getDirectionTo(hexaPacman.getLocation()));
spawningJewel.setActEnabled(true);
}
}
public void reset()
{
status.setText("Tap the screen to the right/left to turn Hexa-Pacman!");
availableJewels.clear();
availableJewels.addAll(allJewels);
score = 0;
hpBar.setHealth(initialHealth);
doRun();
}
public int collide(Actor arg1, Actor collisionPartner)
{
Jewel jewel = (Jewel) collisionPartner;
if (jewel.isExploding())
return 0;
if (headedTowardsHexagonsMouth(jewel))
{
hexaPacman.eat();
hpBar.update(10);
score++;
status.setText("Number of jewels eaten: " + score);
jewel.reset();
}
else
{
hpBar.update(-7);
jewel.explode();
}
return 0;
}
private boolean headedTowardsHexagonsMouth(Jewel jewel)
{
double flyingDirection = hexaPacman.getLocation().getDirectionTo(jewel.getLocation());
return Math.abs(hexaPacman.getDirection() - flyingDirection) < 30;
}
}
// ------- class Pacman -----------
class Pacman extends Actor implements GGMultiTouchListener
{
private GGPanel p;
private int angle = 0;
private final int PER_PERIOD_ANGLE = 10;
private int openMouthCountdown = 0;
public Pacman(GGPanel p)
{
super(true, "hexagon_pacman", 2);
this.p = p;
}
public void reset()
{
setCollisionCircle(new Point(0, 0), 100);
}
public void act()
{
turn(angle);
if (openMouthCountdown > 0)
openMouthCountdown--;
else
show(0);
}
public boolean multiTouchEvent(GGMultiTouch touch)
{
if (!gameGrid.isRunning())
gameGrid.doReset();
if (touch.getEvent() == GGMultiTouch.pointerPress
|| touch.getEvent() == GGMultiTouch.press)
{ // turn on rotating state
PointD userPoint = p.toUserPoint(new Point(touch.getX(), touch.getY()));
if (userPoint.x > 0) //touch on the right side of display
angle = PER_PERIOD_ANGLE;
else
angle = -PER_PERIOD_ANGLE;
} // deactivate rotation on release
else
{
angle = 0;
}
return true;
}
public void eat()
{
show(1);
openMouthCountdown = 4;
}
}
// -------- class Jewel -------------------
class Jewel extends Actor
{
private LinkedList<Jewel> jewels;
private int resetCounter;
public Jewel(LinkedList<Jewel> jewels)
{
super(true, "jewel", 5);
this.jewels = jewels;
}
public void act()
{
//this is quite a bit hacky:
if (resetCounter == 1)
reset();
if (isExploding())
resetCounter--;
else
move();
}
public void reset()
{
resetCounter = 0;
jewels.addLast(this);
setCollisionCircle(new Point(0, 0), 15);
setLocation(new Location(-100, -100)); //out of sight;
setActEnabled(false);
show((int) (Math.random() * 4));
}
public void explode()
{
show(4);
resetCounter = 6;
}
public boolean isExploding()
{
return resetCounter > 0;
}
}
// ----------- class HealthPointBar ---------
class HealthPointBar
{
private GGPanel p;
private double length;
private final double MIN = -9.9;
private final double MAX = 9.9;
private final double MAX_LENGTH = MAX - MIN;
public HealthPointBar(GGPanel p, double initLengthPercent)
{
this.p = p;
setHealth(initLengthPercent);
}
public void update(double percent)
{
//clean old rectangle
p.setPaintColor(Color.WHITE);
p.rectangle(-9.9, -9.9, length, -9.2, true);
p.setPaintColor(Color.GREEN);
length += percent * MAX_LENGTH / 100;
length = Math.min(length, MAX);
length = Math.max(length, MIN);
p.rectangle(-9.9, -9.9, length, -9.2, true);
}
public boolean isGameOver()
{
return length <= MIN;
}
public void setHealth(double percent)
{
length = MAX_LENGTH * percent / 100 + MIN;
update(0);
}
}
|