|
|
|
@@ -0,0 +1,489 @@ |
|
|
|
import hxd.res.DynamicText.Key;
|
|
|
|
import h3d.pass.Default;
|
|
|
|
import ent.Entity;
|
|
|
|
import ent.Object;
|
|
|
|
import hxd.Key in K;
|
|
|
|
|
|
|
|
class EnvPart extends h2d.SpriteBatch.BatchElement {
|
|
|
|
|
|
|
|
public var speed : Float;
|
|
|
|
public var rspeed : Float;
|
|
|
|
|
|
|
|
public function new(t) {
|
|
|
|
super(t);
|
|
|
|
x = Math.random() * Game.LW * 32;
|
|
|
|
y = Math.random() * Game.LH * 32;
|
|
|
|
speed = 6 + Math.random() * 3;
|
|
|
|
rspeed = 0.02 * (1 + Math.random());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@:publicFields
|
|
|
|
class Game extends hxd.App {
|
|
|
|
|
|
|
|
static var LW = 13;
|
|
|
|
static var LH = 13;
|
|
|
|
|
|
|
|
static var LAYER_SOIL = 0;
|
|
|
|
static var LAYER_ENT_UNDER = 1;
|
|
|
|
static var LAYER_COL = 2;
|
|
|
|
static var LAYER_ENT = 3;
|
|
|
|
static var LAYER_CARRY = 4;
|
|
|
|
static var LAYER_HERO = 5;
|
|
|
|
static var LAYER_PARTS = 6;
|
|
|
|
static var LAYER_ENVP = 7;
|
|
|
|
static var LAYER_END = 8;
|
|
|
|
|
|
|
|
|
|
|
|
var currentLevel : Int;
|
|
|
|
|
|
|
|
var tiles : h2d.Tile;
|
|
|
|
var level : Data.Level;
|
|
|
|
var soils : Array<Data.Soil>;
|
|
|
|
var entities : Array<ent.Entity> = [];
|
|
|
|
var world : h2d.Layers;
|
|
|
|
var dbgCol : h2d.TileGroup;
|
|
|
|
var soilLayer : h2d.TileGroup;
|
|
|
|
var pad : hxd.Pad;
|
|
|
|
var allActive : Bool;
|
|
|
|
|
|
|
|
var bg : h2d.Object;
|
|
|
|
var clouds = [];
|
|
|
|
|
|
|
|
var parts : h2d.SpriteBatch;
|
|
|
|
var way : Float = 1.;
|
|
|
|
var bmpTrans : h2d.Bitmap;
|
|
|
|
|
|
|
|
var hueShaderHalf = new h3d.shader.ColorMatrix();
|
|
|
|
var hueValue = 0;
|
|
|
|
|
|
|
|
var title : h2d.Bitmap;
|
|
|
|
var end : h2d.Bitmap;
|
|
|
|
|
|
|
|
var errorSound: hxd.res.Sound;
|
|
|
|
|
|
|
|
function loadGame() {
|
|
|
|
haxe.Timer.delay(function() {
|
|
|
|
for( e in entities.copy() )
|
|
|
|
if( e.hasFlag(NeedActive) )
|
|
|
|
e.remove();
|
|
|
|
bg.visible = false;
|
|
|
|
parts.visible = false;
|
|
|
|
|
|
|
|
var t = new h3d.mat.Texture(LW * 32, LH * 32, [Target]);
|
|
|
|
var old = world.filter;
|
|
|
|
world.filter = null;
|
|
|
|
world.drawTo(t);
|
|
|
|
world.filter = old;
|
|
|
|
bmpTrans = new h2d.Bitmap(h2d.Tile.fromTexture(t));
|
|
|
|
|
|
|
|
bg.visible = true;
|
|
|
|
parts.visible = true;
|
|
|
|
|
|
|
|
initLevel();
|
|
|
|
|
|
|
|
world.add(bmpTrans, LAYER_ENT - 1);
|
|
|
|
|
|
|
|
},0);
|
|
|
|
}
|
|
|
|
|
|
|
|
function initLevel()
|
|
|
|
{
|
|
|
|
level = Data.level.all[currentLevel];
|
|
|
|
if( level == null )
|
|
|
|
return;
|
|
|
|
|
|
|
|
soils = level.soils.decode(Data.soil.all);
|
|
|
|
while( soilLayer.numChildren > 0 )
|
|
|
|
soilLayer.getChildAt(0).remove();
|
|
|
|
|
|
|
|
// Build game board
|
|
|
|
var empty = tiles.sub(0, 2 * 32, 32, 32);
|
|
|
|
var edgeTile = tiles.sub(2*32, 2 * 32, 32, 32);
|
|
|
|
soilLayer.clear();
|
|
|
|
for( y in 0...LH ) {
|
|
|
|
for( x in 0...LW ) {
|
|
|
|
var index = x + y * LW;
|
|
|
|
var s = soils[x + y * LW];
|
|
|
|
if(x > 1 && x < 11 && y > 1 && y < 11)
|
|
|
|
{
|
|
|
|
// check if it is the corner or center tile
|
|
|
|
if((x==y || (x + y) == 12)&& (x == 2 || x == 6 || x == 10) )
|
|
|
|
{
|
|
|
|
soilLayer.add(x * 32, y * 32, edgeTile);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
soilLayer.add(x * 32, y * 32, empty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// place object on the board
|
|
|
|
createObject(x, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle interactions
|
|
|
|
var prevKind = null;
|
|
|
|
var clickedObjKind = null;
|
|
|
|
var clickedObj = null;
|
|
|
|
var isFirstClick = true;
|
|
|
|
var sX = 0, sY = 0;
|
|
|
|
var eX = 0, eY = 0;
|
|
|
|
var interaction = new h2d.Interactive(1000, 1000, soilLayer);
|
|
|
|
var count = 0;
|
|
|
|
interaction.onClick = function(event : hxd.Event) {
|
|
|
|
var xPos = Std.int((event.relX)/32);
|
|
|
|
var yPos = Std.int((event.relY)/32);
|
|
|
|
|
|
|
|
if (isFirstClick == true){
|
|
|
|
sX = xPos;
|
|
|
|
sY = yPos;
|
|
|
|
//trace (isFirstClick);
|
|
|
|
clickedObj = Std.downcast(pick(sX, sY), Object);
|
|
|
|
if(clickedObj != null)
|
|
|
|
{
|
|
|
|
isFirstClick = false;
|
|
|
|
// Treat the purple circle and the purple gem as same kind
|
|
|
|
if (isKing(clickedObj.kind))
|
|
|
|
clickedObjKind = Data.ObjectKind.Exit;
|
|
|
|
else
|
|
|
|
clickedObjKind = clickedObj.kind;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
trace (prevKind);
|
|
|
|
eX = xPos;
|
|
|
|
eY = yPos;
|
|
|
|
isFirstClick = true;
|
|
|
|
//trace (isFirstClick);
|
|
|
|
var destinationObj = Std.downcast(pick(eX, eY), Object);
|
|
|
|
|
|
|
|
var isAcceptableMove = true;
|
|
|
|
if (destinationObj == null && // destination tile is empty
|
|
|
|
clickedObj != null && // you have clicked an object to move
|
|
|
|
prevKind != clickedObjKind && // alternating turns
|
|
|
|
(eX == sX || eY == sY)) // moving horizontally or vertically
|
|
|
|
{
|
|
|
|
|
|
|
|
// Check that there are no blockade between start and end
|
|
|
|
var isHorizontal = false;
|
|
|
|
var distanceToMove = 0;
|
|
|
|
var tempX = sX;
|
|
|
|
var tempY = sY;
|
|
|
|
if (eX == sX){
|
|
|
|
distanceToMove = eY - sY;
|
|
|
|
if (distanceToMove < 0){
|
|
|
|
tempY--;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
tempY++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (eY == sY){
|
|
|
|
isHorizontal = true;
|
|
|
|
distanceToMove = eX - sX;
|
|
|
|
if (distanceToMove < 0){
|
|
|
|
tempX--;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
tempX++;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
trace ('sX, sY: ' + sX + ',' + sY);
|
|
|
|
trace ('eX, eY: ' + eX + ',' + eY);
|
|
|
|
|
|
|
|
trace ('isHorizontal: ' + isHorizontal);
|
|
|
|
trace ('distanceToMove: ' + distanceToMove);
|
|
|
|
|
|
|
|
|
|
|
|
while (distanceToMove != 0){
|
|
|
|
var oB = Std.downcast(pick(tempX, tempY), Object);
|
|
|
|
|
|
|
|
trace ('tempX, tempY: ' + tempX + ',' + tempY);
|
|
|
|
if (oB == null && isHorizontal){
|
|
|
|
if (distanceToMove < 0)
|
|
|
|
tempX--;
|
|
|
|
else
|
|
|
|
tempX++;
|
|
|
|
}
|
|
|
|
else if (oB == null && !isHorizontal){
|
|
|
|
if (distanceToMove < 0)
|
|
|
|
tempY--;
|
|
|
|
else
|
|
|
|
tempY++;
|
|
|
|
}
|
|
|
|
else if (oB != null){
|
|
|
|
trace ('oB is not null ');
|
|
|
|
isAcceptableMove = false;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
if (distanceToMove > 0)
|
|
|
|
distanceToMove--;
|
|
|
|
else
|
|
|
|
distanceToMove++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if a non-player object is moving to the cornre
|
|
|
|
if((eX == 2 || eX == 10) && (eY == 2 || eY == 10))
|
|
|
|
{
|
|
|
|
if (!isKing(clickedObj.kind)){
|
|
|
|
isAcceptableMove = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move the object
|
|
|
|
if (isAcceptableMove){
|
|
|
|
// remove from the source position
|
|
|
|
clickedObj.remove();
|
|
|
|
|
|
|
|
// create the object in the destination position
|
|
|
|
var movedObj = new ent.Object(clickedObj.kind, eX, eY);
|
|
|
|
if ((eX == 2 || eX == 10) && (eY == 2 || eY == 10)){
|
|
|
|
|
|
|
|
// End game if reached the corner
|
|
|
|
if (isKing(movedObj.kind)){
|
|
|
|
displayEnd();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
prevKind = clickedObjKind;
|
|
|
|
|
|
|
|
//To Do: Add Logic for Capture
|
|
|
|
/*if (eX == sX){
|
|
|
|
if (distanceToMove > 0){
|
|
|
|
var obJ = Std.downcast(pick(eX, eY + 2), Object);
|
|
|
|
var Obj = Std.downcast(pick(eX, eY + 1), Object);
|
|
|
|
if (obJ != null && Obj != null){
|
|
|
|
if (obJ.kind == movedObj.kind && Obj.kind != movedObj.kind){
|
|
|
|
if (movedObj.kind == Square3)
|
|
|
|
movedObj.kind = Exit;
|
|
|
|
else if (obJ.kind == Square3){
|
|
|
|
obJ.kind = Exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
isAcceptableMove = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!isAcceptableMove && errorSound != null)
|
|
|
|
{
|
|
|
|
errorSound.play(false, 0.5 + Math.random() * 0.5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function displayEnd() {
|
|
|
|
end = new h2d.Bitmap(hxd.Res.end_png.toTile());
|
|
|
|
end.scale(1);
|
|
|
|
world.add(end, LAYER_END);
|
|
|
|
// Pause for 5 sec and then end the game
|
|
|
|
haxe.Timer.delay(function() {
|
|
|
|
Game.restartGame();
|
|
|
|
}, 5000);
|
|
|
|
}
|
|
|
|
|
|
|
|
function createObject(x, y) : ent.Entity {
|
|
|
|
var myX = x * 1;
|
|
|
|
var myY = y * 1;
|
|
|
|
if(x==6 && y == 6)
|
|
|
|
{
|
|
|
|
return new ent.Object(Square2, x, y);
|
|
|
|
}
|
|
|
|
else if ( ((x > 4 && x < 8) && ((y == 2) || (y == 10))) ||
|
|
|
|
((y > 4 && y < 8) && ((x == 2) || (x == 10))) ||
|
|
|
|
(x == 6 && (y == 3 || y == 9)) ||
|
|
|
|
(y == 6 && (x == 3 || x == 9))
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return new ent.Object(Square1, x, y);
|
|
|
|
}
|
|
|
|
else if ( (x == 6 && (y > 3 && y < 6)) ||
|
|
|
|
(x == 6 && (y > 6 && y < 9)) ||
|
|
|
|
(y == 6 && (x > 3 && x < 6)) ||
|
|
|
|
(y == 6 && (x > 6 && x < 9))
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return new ent.Object(Exit, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
function isKing(kind : Data.ObjectKind ){
|
|
|
|
return (kind == Square2);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getSoil( x, y ) : Data.SoilKind {
|
|
|
|
if( x < 0 || y < 0 || x >= LW || y >= LH )
|
|
|
|
return Block;
|
|
|
|
return soils[x + y * LH].id;
|
|
|
|
}
|
|
|
|
|
|
|
|
function pick( x : Float, y : Float ) {
|
|
|
|
var ix = Std.int(x);
|
|
|
|
var iy = Std.int(y);
|
|
|
|
for( e in entities )
|
|
|
|
{
|
|
|
|
if( Std.int(e.x) == ix && Std.int(e.y) == iy )
|
|
|
|
{
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
override function init() {
|
|
|
|
|
|
|
|
errorSound = hxd.Res.load("sfx/error.wav").toSound();
|
|
|
|
|
|
|
|
// preload sounds
|
|
|
|
for( s in hxd.Res.load("sfx") )
|
|
|
|
s.toSound().getData();
|
|
|
|
|
|
|
|
s2d.scaleMode = Stretch(LW * 32, LH * 32);
|
|
|
|
currentLevel = 1;
|
|
|
|
world = new h2d.Layers(s2d);
|
|
|
|
world.filter = new h2d.filter.Bloom(0.5,0.2,3);
|
|
|
|
tiles = hxd.Res.tiles.toTile();
|
|
|
|
soilLayer = new h2d.TileGroup(tiles);
|
|
|
|
|
|
|
|
bg = new h2d.Object(world);
|
|
|
|
bg.filter = new h2d.filter.Blur(3);
|
|
|
|
bg.filter.smooth = true;
|
|
|
|
var tbg = tiles.sub(32 * 3, 64, 32, 32);
|
|
|
|
tbg.scaleToSize(LW * 32, LH * 32);
|
|
|
|
new h2d.Bitmap(tbg, bg).addShader(hueShaderHalf);
|
|
|
|
|
|
|
|
// Display background clouds
|
|
|
|
var rnd = new hxd.Rand(42);
|
|
|
|
var ctiles = [for( i in 0...3 ) tiles.sub(i * 32 * 3, 192, 32 * 3, 64, -32 * 3 >> 1, -32)];
|
|
|
|
for( i in 0...100 ) {
|
|
|
|
var b = new h2d.Bitmap(ctiles[rnd.random(ctiles.length)], bg);
|
|
|
|
b.smooth = true;
|
|
|
|
b.addShader(hueShaderHalf);
|
|
|
|
clouds.push({ sc : 0.7 + rnd.rand(), x : rnd.rand() * (LW * 32 + 200) - 100, y : rnd.rand() * (LH * 32 + 200) - 100, speed : rnd.rand() + 1, spr : b, t : Math.random() * Math.PI * 2 });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Display the flying snow
|
|
|
|
var ptiles = hxd.Res.envParts.toTile().split();
|
|
|
|
parts = new h2d.SpriteBatch(ptiles[0]);
|
|
|
|
world.add(parts, LAYER_ENVP);
|
|
|
|
for( i in 0...100 )
|
|
|
|
parts.add(new EnvPart(ptiles[Std.random(ptiles.length)]));
|
|
|
|
world.add(soilLayer, LAYER_SOIL);
|
|
|
|
|
|
|
|
pad = hxd.Pad.createDummy();
|
|
|
|
hxd.Pad.wait(function(p) pad = p);
|
|
|
|
|
|
|
|
// Display title and instruction to start game
|
|
|
|
title = new h2d.Bitmap(hxd.Res.title.toTile(), world);
|
|
|
|
var tf = new h2d.Text(hxd.res.DefaultFont.get(), title);
|
|
|
|
tf.textColor = 0;
|
|
|
|
tf.text = "Press space to start";
|
|
|
|
tf.x=180;
|
|
|
|
tf.y = 180;
|
|
|
|
}
|
|
|
|
|
|
|
|
override function update( dt : Float ) {
|
|
|
|
dt *= 60; // old dt support
|
|
|
|
|
|
|
|
if( bmpTrans != null ) {
|
|
|
|
bmpTrans.alpha -= 0.05 * dt;
|
|
|
|
if( bmpTrans.alpha < 0 ) {
|
|
|
|
bmpTrans.tile.getTexture().dispose();
|
|
|
|
bmpTrans.remove();
|
|
|
|
bmpTrans = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for( e in entities.copy() )
|
|
|
|
e.update(dt);
|
|
|
|
|
|
|
|
var ang = -0.3;
|
|
|
|
for( c in clouds ) {
|
|
|
|
var ds = c.speed * dt * 0.3 * way;
|
|
|
|
|
|
|
|
c.t += ds * 0.01;
|
|
|
|
c.spr.setScale(1 + Math.sin(c.t) * 0.2);
|
|
|
|
c.spr.scaleX *= c.sc;
|
|
|
|
|
|
|
|
c.x += Math.cos(ang) * ds;
|
|
|
|
c.y += Math.sin(ang) * ds;
|
|
|
|
c.spr.x = c.x;
|
|
|
|
c.spr.y = c.y;
|
|
|
|
if( c.x > LW * 32 + 100 )
|
|
|
|
c.x -= LW * 32 + 300;
|
|
|
|
if( c.y > LH * 32 + 100 )
|
|
|
|
c.y -= LH * 32 + 300;
|
|
|
|
if( c.x < -100 )
|
|
|
|
c.x += LW * 32 + 300;
|
|
|
|
if( c.y < -100 )
|
|
|
|
c.y += LH * 32 + 300;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
parts.hasRotationScale = true;
|
|
|
|
for( p in parts.getElements() ) {
|
|
|
|
var p = cast(p, EnvPart);
|
|
|
|
var ds = dt * p.speed * way;
|
|
|
|
p.x += Math.cos(ang) * ds;
|
|
|
|
p.y += Math.sin(ang) * ds;
|
|
|
|
p.rotation += ds * p.rspeed;
|
|
|
|
if( p.x > LW * 32 )
|
|
|
|
p.x -= LW * 32;
|
|
|
|
if( p.y > LH * 32 )
|
|
|
|
p.y -= LH * 32;
|
|
|
|
if( p.y < 0 )
|
|
|
|
p.y += LH * 32;
|
|
|
|
if( p.x < 0 )
|
|
|
|
p.x += LW * 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( title != null && title.alpha < 1 ) {
|
|
|
|
title.alpha -= 0.01 * dt;
|
|
|
|
if( title.alpha < 0 ) {
|
|
|
|
title.remove();
|
|
|
|
title = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( title != null && title.alpha == 1 ) {
|
|
|
|
if(K.isPressed(K.SPACE)) {
|
|
|
|
title.alpha = 0.99;
|
|
|
|
loadGame();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static var inst : Game;
|
|
|
|
|
|
|
|
static function main() {
|
|
|
|
#if js
|
|
|
|
hxd.Res.initEmbed();
|
|
|
|
#else
|
|
|
|
hxd.res.Resource.LIVE_UPDATE = true;
|
|
|
|
hxd.Res.initLocal();
|
|
|
|
#end
|
|
|
|
Data.load(hxd.Res.data.entry.getText());
|
|
|
|
inst = new Game();
|
|
|
|
}
|
|
|
|
|
|
|
|
static function restartGame() {
|
|
|
|
Game.main();
|
|
|
|
}
|
|
|
|
} |