Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import Drag;
- import luxe.Vector;
- import luxe.Text;
- import luxe.Color;
- import luxe.Entity;
- import luxe.Sprite;
- import luxe.tween.Actuate;
- // something on a tile with a geom
- class Actor {
- public function new() {}
- public var tile : Tile;
- public var geom : Sprite;
- }
- class Piece {
- public function new() {}
- public var actor : Actor;
- public var kind : PieceKind;
- public var team : Int;
- }
- class Structure {
- public function new() {}
- public var actor : Actor;
- }
- enum PieceKind {
- Rook;
- Pawn;
- King;
- Queen;
- Bishop;
- Knight;
- }
- class Puzzle {
- var root : Entity;
- var tile_map : TileMap;
- var drag : Drag;
- var can_move : Bool;
- var turns : Int;
- var player : Piece;
- var structures : Array<Structure>;
- var pieces : Array<Piece>;
- var ADJACENT_NEIGHBORS : Array<Direction> = [
- North,
- East,
- South,
- West,
- ];
- var MOORE_NEIGHBORS : Array<Direction> = [
- North,
- East,
- South,
- West,
- NorthEast,
- NorthWest,
- SouthEast,
- SouthWest,
- ];
- public function new() {
- Luxe.events.listen('resize', onresize);
- Luxe.events.listen('dragdown', ondragdown);
- Luxe.events.listen('dragmove', ondragmove);
- Luxe.events.listen('dragup', ondragup);
- }
- public function play() {
- root = new Entity();
- turns = 0;
- var w : Int = 5;
- var h : Int = 6;
- tile_map = new TileMap();
- tile_map.init_tiles_to_size(w, h);
- tile_map.tile_size = new Vector(128, 128);
- var texture_info = Main.texture_atlas.get_texture('water');
- for (tile in tile_map.tiles_array) {
- var geom : Sprite = tile.geom;
- geom.texture = texture_info.texture;
- geom.uv = texture_info.uv;
- geom.depth = -1;
- geom.parent = root;
- geom.size.copy_from(tile_map.tile_size);
- var i : Int = tile.i;
- var j : Int = tile.j;
- if ((i % 2 == 0 && j % 2 != 0)
- || (i % 2 != 0 && j % 2 == 0)) {
- geom.color.rgb(0xe3ded3);
- } else {
- geom.visible = false;
- }
- var x : Float = (i - w * 0.5 + 0.5) * tile_map.tile_size.x;
- var y : Float = (j - h * 0.5 + 0.5) * tile_map.tile_size.y;
- geom.pos.set_xy(x, y);
- geom.active = false;
- }
- can_move = true;
- player = make_player(Queen);
- move_actor(player.actor, tile_map.tiles_array[3]);
- pieces = [];
- structures = [];
- for (i in 0...w) {
- var tile : Tile = tile_map.get_tile_at_index(i, 0);
- var structure = make_structure();
- move_actor(structure.actor, tile);
- tile.geom.visible = false;
- structures.push(structure);
- }
- arrange();
- }
- public function reset() {
- Luxe.scene.empty();
- }
- function set_sprite_texture(sprite:Sprite, texture_name:String) {
- var texture_info = Main.texture_atlas.get_texture(texture_name);
- sprite.texture = texture_info.texture;
- sprite.size = texture_info.size.clone();
- sprite.uv = texture_info.uv.clone();
- }
- function make_actor() {
- var actor = new Actor();
- actor.geom = new Sprite({
- parent: root,
- });
- actor.geom.color.rgb(0xffffff);
- Utils.fit_vector_to_size(actor.geom.size, tile_map.tile_size.x * 0.9, tile_map.tile_size.y * 0.9);
- return actor;
- }
- function make_piece(piece_kind:PieceKind, team:Int) {
- var piece = new Piece();
- piece.actor = make_actor();
- set_piece_kind(piece, piece_kind);
- piece.team = team;
- if (team > 0) {
- piece.actor.geom.color.rgb(0xff0000);
- }
- return piece;
- }
- function set_piece_kind(piece:Piece, piece_kind:PieceKind) {
- var textures : Map<PieceKind,String> = [
- Pawn => 'pawn',
- Rook => 'rook',
- King => 'king',
- Queen => 'queen',
- Bishop => 'bishop',
- Knight => 'knight',
- ];
- set_sprite_texture(piece.actor.geom, textures.get(piece_kind));
- piece.actor.geom.name = textures.get(piece_kind);
- piece.kind = piece_kind;
- }
- function make_player(piece_kind:PieceKind) {
- var piece = make_piece(piece_kind, 0);
- piece.actor.geom.name = 'player';
- return piece;
- }
- function make_structure() {
- var structure = new Structure();
- var actor = make_actor();
- set_sprite_texture(actor.geom, 'gate');
- actor.geom.name = 'structure';
- actor.geom.size.copy_from(tile_map.tile_size);
- actor.geom.size.y *= 0.8;
- actor.geom.color.rgb(0x969184);
- actor.geom.depth = 10;
- structure.actor = actor;
- return structure;
- }
- function spawn_piece() {
- var available_structures : Array<Structure>= [];
- for (structure in structures) {
- var tile : Tile = structure.actor.tile;
- var piece : Piece = query_piece_by_tile(tile);
- if (piece == null) available_structures.push(structure);
- }
- if (available_structures.length == 0) return trace('no available structures to spawn');
- var random_index : Int = Math.floor(Math.random() * available_structures.length);
- var structure = available_structures[random_index];
- var tile : Tile = structure.actor.tile;
- if (tile == null) return trace('no tile on structure?');
- var piece = make_piece(Pawn, 1);
- move_actor(piece.actor, tile);
- piece.actor.geom.pos.y -= tile_map.tile_size.y;
- move_actor(piece.actor, tile);
- pieces.push(piece);
- }
- function move_actor(actor:Actor, new_tile:Tile) {
- var old_tile : Tile = actor.tile;
- if (old_tile != null) {
- var anim = Animate.animate_vector(actor.geom.pos);
- anim.duration = 0.2;
- anim.dst.copy_from(new_tile.geom.pos);
- anim.easing = luxe.tween.easing.Cubic.easeInOut;
- } else {
- actor.geom.pos.copy_from(new_tile.geom.pos);
- }
- actor.tile = new_tile;
- trace('moved ${actor.geom.name} from $old_tile to $new_tile');
- }
- // gameplay code
- function get_direction_from_components(di:Int, dj:Int):Direction {
- if (di == 0 && dj == 1) return South;
- if (di == 0 && dj == -1) return North;
- if (di == 1 && dj == 0) return East;
- if (di == -1 && dj == 0) return West;
- if (di == 1 && dj == -1) return NorthEast;
- if (di == -1 && dj == -1) return NorthWest;
- if (di == 1 && dj == 1) return SouthEast;
- if (di == -1 && dj == 1) return SouthWest;
- return null;
- }
- function query_tile_in_direction(tile:Tile, direction:Direction) {
- var i : Int = tile.i;
- var j : Int = tile.j;
- switch (direction) {
- case North: { j -= 1; };
- case South: { j += 1; };
- case East: { i += 1; };
- case West: { i -= 1; };
- case NorthEast: { i += 1; j -= 1; };
- case NorthWest: { i -= 1; j -= 1; };
- case SouthEast: { i += 1; j += 1; };
- case SouthWest: { i -= 1; j += 1; };
- }
- return tile_map.get_tile_at_index(i, j);
- }
- function query_tiles_in_direction(tile:Tile, direction:Direction, ?limit:Int = 0) {
- var tiles : Array<Tile> = [];
- var curr_tile : Tile = tile;
- while (tiles.length < limit || limit <= 0) {
- var next_tile : Tile = query_tile_in_direction(curr_tile, direction);
- if (next_tile == null) break;
- tiles.push(next_tile);
- curr_tile = next_tile;
- }
- return tiles;
- }
- function query_structure_by_tile(tile:Tile) {
- for (structure in structures) {
- if (structure.actor.tile == tile) return structure;
- }
- return null;
- }
- function query_piece_by_tile(tile:Tile) {
- if (player.actor.tile == tile) return player;
- for (piece in pieces) {
- if (piece.actor.tile == tile) return piece;
- }
- return null;
- }
- function is_piece_in_structure(piece:Piece) {
- var tile : Tile = piece.actor.tile;
- var structure : Structure = query_structure_by_tile(tile);
- return structure != null;
- }
- function get_valid_moves_for_piece(piece:Piece) {
- var valid_moves : Array<Tile> = [];
- var kind : PieceKind = piece.kind;
- var team : Int = piece.team;
- var actor : Actor = piece.actor;
- var curr_tile : Tile = piece.actor.tile;
- function get_possible_moves_for_directions(directions:Array<Direction>, limit:Int) {
- var possible_moves : Array<Tile> = [];
- for (direction in directions) {
- var tiles : Array<Tile> = query_tiles_in_direction(curr_tile, direction, limit);
- for (tile in tiles) {
- var hit_piece : Piece = query_piece_by_tile(tile);
- if (hit_piece != null) {
- if (hit_piece.team != team) possible_moves.push(tile);
- break;
- }
- var hit_structure : Structure = query_structure_by_tile(tile);
- if (hit_structure != null) break;
- possible_moves.push(tile);
- }
- }
- return possible_moves;
- }
- switch(kind) {
- case Pawn: {
- var possible_moves : Array<Tile> = [];
- var attackable_tiles : Array<Tile> = [];
- attackable_tiles.push(tile_map.get_tile_at_offset(curr_tile, 1, 1));
- attackable_tiles.push(tile_map.get_tile_at_offset(curr_tile, -1, 1));
- for (tile in attackable_tiles) {
- var attackable_piece = query_piece_by_tile(tile);
- if (attackable_piece == null) continue;
- if (attackable_piece.team == team) continue;
- possible_moves.push(tile);
- }
- var traversable_tile = tile_map.get_tile_at_offset(curr_tile, 0, 1);
- if (traversable_tile != null) {
- if (query_piece_by_tile(traversable_tile) == null) {
- possible_moves.push(traversable_tile);
- }
- }
- valid_moves = Lambda.array(Lambda.filter(possible_moves, function(tile:Tile) {
- var piece = query_piece_by_tile(tile);
- if (piece == null) return true;
- if (piece.team == team) return false;
- return true;
- }));
- };
- case Knight: {
- var possible_moves : Array<Tile> = [];
- for (direction in [North, South, East, West]) {
- var tiles : Array<Tile> = query_tiles_in_direction(curr_tile, direction, 2);
- if (tiles.length < 2) continue;
- var pivot_tile : Tile = tiles[1];
- var tile_a : Tile = null;
- var tile_b : Tile = null;
- if (direction == North || direction == South) {
- tile_a = query_tile_in_direction(pivot_tile, East);
- tile_b = query_tile_in_direction(pivot_tile, West);
- } else {
- tile_a = query_tile_in_direction(pivot_tile, North);
- tile_b = query_tile_in_direction(pivot_tile, South);
- }
- if (tile_a != null) possible_moves.push(tile_a);
- if (tile_b != null) possible_moves.push(tile_b);
- }
- valid_moves = possible_moves;
- };
- case Rook: {
- valid_moves = get_possible_moves_for_directions(ADJACENT_NEIGHBORS, -1);
- };
- case Bishop: {
- valid_moves = get_possible_moves_for_directions(ADJACENT_NEIGHBORS, -1);
- };
- case Queen: {
- valid_moves = get_possible_moves_for_directions(MOORE_NEIGHBORS, -1);
- };
- case King: {
- valid_moves = get_possible_moves_for_directions(MOORE_NEIGHBORS, 1);
- };
- default: {
- trace('no movement pattern defined for $kind');
- };
- }
- // you can only move out of a structure
- valid_moves = Lambda.array(Lambda.filter(valid_moves, function(tile:Tile) {
- var structure = query_structure_by_tile(tile);
- return structure == null;
- }));
- return valid_moves;
- }
- function sim_forward() {
- trace('sim forward for turn $turns');
- var piece_values : Map<PieceKind,Int> = [
- Pawn => 1,
- Rook => 5,
- ];
- function compare_pieces(a:Piece, b:Piece) {
- // units in structures move last
- var a_in_structure = is_piece_in_structure(a);
- var b_in_structure = is_piece_in_structure(b);
- if (a_in_structure && !b_in_structure) return 1;
- else if (!a_in_structure && b_in_structure) return -1;
- // units of greatest value and then map y height
- var a_value : Int = piece_values.get(a.kind);
- var b_value : Int = piece_values.get(b.kind);
- if (a_value > b_value) return 1;
- else if (a_value == b_value) {
- if (a.actor.tile.j < b.actor.tile.j) return 1
- else if (a.actor.tile.j == b.actor.tile.j) return 0;
- else return -1;
- } else return -1;
- }
- haxe.ds.ArraySort.sort(pieces, compare_pieces);
- var player_tile : Tile = player.actor.tile;
- for (piece in pieces) {
- var kind : PieceKind = piece.kind;
- var team : Int = piece.team;
- var actor : Actor = piece.actor;
- var curr_tile : Tile = piece.actor.tile;
- var next_tile : Tile = null;
- var inside_structure : Bool = query_structure_by_tile(curr_tile) != null;
- if (inside_structure) {
- // no move if we need to exit our structure and
- // the player is blocking us
- var entrance_tile = tile_map.get_tile_at_offset(curr_tile, 0, 1);
- var hit_piece = query_piece_by_tile(entrance_tile);
- if (entrance_tile != player_tile && hit_piece == null) {
- next_tile = entrance_tile;
- } else {
- var src_y : Float = curr_tile.geom.pos.y;
- var dst_y : Float = src_y + (entrance_tile.geom.pos.y - src_y) * 0.2;
- Actuate.tween(actor.geom.pos, 0.1, { y: dst_y })
- .ease(luxe.tween.easing.Cubic.easeInOut)
- .onComplete(function() {
- Actuate.tween(actor.geom.pos, 0.1, { y: src_y })
- .ease(luxe.tween.easing.Cubic.easeInOut);
- });
- }
- } else {
- var possible_moves : Array<Tile> = get_valid_moves_for_piece(piece);
- if (possible_moves.length == 0) {
- trace('no possible moves for $kind on $curr_tile');
- continue;
- }
- possible_moves = Lambda.array(Lambda.filter(possible_moves, function(tile:Tile) {
- if (player_tile == tile && !can_move) return false;
- return true;
- }));
- function compare_moves(a:Tile, b:Tile) {
- if (player_tile == a) return 1;
- if (player_tile == b) return -1;
- var dist_a = tile_map.get_dist_between_tiles(player_tile, a);
- var dist_b = tile_map.get_dist_between_tiles(player_tile, b);
- if (dist_a < dist_b) return 1;
- else if (dist_a == dist_b) return 0;
- else return -1;
- }
- haxe.ds.ArraySort.sort(possible_moves, compare_moves);
- next_tile = possible_moves.pop();
- }
- if (next_tile == null) {
- trace('no move for $kind on $curr_tile');
- continue;
- }
- move_actor(actor, next_tile);
- var on_end_tile : Bool = next_tile.j == tile_map.h - 1;
- if (on_end_tile && kind == Pawn) {
- Luxe.timer.schedule(0.2, function() {
- set_piece_kind(piece, Queen);
- trace('promoted!');
- });
- }
- // TODO: improve game over...
- if (next_tile == player_tile) {
- can_move = false;
- Luxe.timer.schedule(0.2, function() {
- trace('game over');
- player.actor.geom.visible = false;
- });
- }
- }
- spawn_piece();
- }
- public function visualize_player_moves() {
- var valid_moves = get_valid_moves_for_piece(player);
- var markers = [];
- for (tile in valid_moves) {
- var marker = new Sprite({
- parent: root,
- });
- marker.color.rgb(0xff0000);
- marker.size.copy_from(tile_map.tile_size);
- marker.pos.copy_from(tile.geom.pos);
- markers.push(marker);
- }
- Luxe.timer.schedule(0.5, function() {
- for (marker in markers) marker.destroy();
- });
- }
- // input
- function ondragdown(e:DragEvent) {
- // if i want to move to tapping tiles and dragging...
- // lets start by only supporting tap (less fatigueing)
- // so you tap on a tile and if it is valid then
- // it works
- if (!can_move) return;
- if (drag != null) return;
- var valid_moves = get_valid_moves_for_piece(player);
- // check if we are focusing any particular tile..
- drag = {
- id: e.id,
- pos: e.pos,
- origin: e.pos,
- delta: new Vector(),
- elapsed: 0,
- data: valid_moves,
- }
- }
- function ondragmove(e:DragEvent) {
- if (drag == null) return;
- var delta : Vector = Vector.Subtract(e.pos, drag.pos);
- var moved : Vector = Vector.Subtract(e.pos, drag.origin);
- drag.pos = e.pos;
- var deadzone : Float = 32;
- if (moved.length < deadzone) return;
- var theta : Float = moved.angle2D;
- var cardinal : Float = Utils.nearest_cardinal_radians(theta);
- var i : Int = player.actor.tile.i;
- var j : Int = player.actor.tile.j;
- var di : Int = Math.round(Math.cos(cardinal));
- var dj : Int = Math.round(Math.sin(cardinal));
- var new_tile : Tile = null;
- var direction = get_direction_from_components(di, dj);
- var tiles = query_tiles_in_direction(player.actor.tile, direction);
- for (tile in tiles) {
- if (query_structure_by_tile(tile) != null) {
- break;
- }
- if (query_piece_by_tile(tile) != null) {
- new_tile = tile;
- break;
- }
- new_tile = tile;
- }
- var t : Float = Math.min((moved.length - deadzone) / 170, 1);
- t = Math.pow(t, 0.5);
- var vec_to_tile : Vector = new Vector(di * 128, dj * 128);
- var displacement : Vector = Vector.Multiply(vec_to_tile, t * 0.1);
- /*
- player.actor.geom.pos = Vector.Add(player.actor.tile.geom.pos, displacement);
- if (new_tile == null) {
- var squash : Vector = Vector.Multiply(vec_to_tile.normalized, 0.2 * t);
- player.actor.geom.scale = new Vector(1 - Math.abs(squash.x), 1 - Math.abs(squash.y));
- } else {
- Actuate.tween(player.actor.geom.scale, 0.2, new Vector(1.0, 1.0));
- }
- */
- }
- function ondragup(e:DragEvent) {
- if (drag == null) return;
- Actuate.tween(player.actor.geom.scale, 0.2, new Vector(1.0, 1.0));
- var moved : Vector = Vector.Subtract(e.pos, drag.origin);
- var elapsed : Float = drag.elapsed;
- var valid_moves : Array<Tile> = cast drag.data;
- var hit_tile : Tile = tile_map.get_tile_at_pos(drag.pos);
- var new_tile : Tile = null;
- for (tile in valid_moves) {
- if (tile == hit_tile) {
- new_tile = hit_tile;
- break;
- }
- }
- drag = null;
- if (new_tile == null) return;
- var hit_piece : Piece = query_piece_by_tile(new_tile);
- if (hit_piece != null) {
- pieces.remove(hit_piece);
- Luxe.timer.schedule(0.2, function() {
- hit_piece.actor.geom.visible = false;
- });
- }
- move_actor(player.actor, new_tile);
- turns++;
- Luxe.timer.schedule(0.3, sim_forward);
- var deadzone : Float = 32;
- if (elapsed < 0.1) deadzone = 64;
- if (elapsed > 0.3) deadzone = 128;
- if (moved.length < deadzone) {
- return;
- /*
- var tile : Tile = tile_map.get_tile_at_pos(drag.pos);
- if (tile == null) {
- Actuate.tween(player.actor.geom.pos, 0.1, player.actor.tile.geom.pos);
- return;
- }
- var hit_piece : Piece = query_piece_by_tile(tile);
- if (hit_piece != null && hit_piece != player) {
- pieces.remove(hit_piece);
- Luxe.timer.schedule(0.2, function() {
- hit_piece.actor.geom.visible = false;
- });
- }
- turns++;
- Luxe.timer.schedule(0.2, sim_forward);
- move_actor(player.actor, tile);
- return;
- */
- }
- /*
- var theta : Float = moved.angle2D;
- var cardinal : Float = Utils.nearest_cardinal_radians(theta);
- var i : Int = player.actor.tile.i;
- var j : Int = player.actor.tile.j;
- var di : Int = Math.round(Math.cos(cardinal));
- var dj : Int = Math.round(Math.sin(cardinal));
- var new_tile : Tile = null;
- var direction = get_direction_from_components(di, dj);
- var tiles = query_tiles_in_direction(player.actor.tile, direction);
- for (tile in tiles) {
- if (query_structure_by_tile(tile) != null) {
- break;
- }
- var hit_piece : Piece = query_piece_by_tile(tile);
- if (hit_piece != null) {
- new_tile = tile;
- break;
- }
- new_tile = tile;
- }
- if (new_tile == null) {
- Actuate.tween(player.actor.geom.pos, 0.1, player.actor.tile.geom.pos);
- return;
- }
- var hit_piece : Piece = query_piece_by_tile(new_tile);
- if (hit_piece != null) {
- pieces.remove(hit_piece);
- Luxe.timer.schedule(0.2, function() {
- hit_piece.actor.geom.visible = false;
- });
- }
- // sometimes we may want this to be slower?
- move_actor(player.actor, new_tile);
- turns++;
- Luxe.timer.schedule(0.3, sim_forward);
- */
- }
- // upkeep
- public function update(dt:Float) {
- if (drag != null) drag.elapsed += dt;
- }
- function arrange() {
- var tile_map_w : Float = tile_map.w * tile_map.tile_size.x;
- var tile_map_h : Float = tile_map.h * tile_map.tile_size.y;
- var w : Float = Luxe.screen.width;
- var h : Float = Luxe.screen.height;
- var pad : Float = Math.min(w, h) * 0.1;
- var s : Float = Math.min((w - pad) /tile_map_w, (h - pad) / tile_map_h);
- root.scale.set_xy(s, s);
- }
- function onresize(_) arrange();
- }
- class Tile {
- public function new() {}
- public function toString() return '($i, $j)';
- public var tile_map : TileMap;
- public var i : Int;
- public var j : Int;
- public var geom : Sprite;
- }
- enum Direction {
- North;
- South;
- East;
- West;
- NorthEast;
- NorthWest;
- SouthEast;
- SouthWest;
- }
- class TileMap {
- public var tiles_array : Array<Tile>;
- public var tiles_indexed : Array<Array<Tile>>;
- public var tile_size : Vector;
- public var w : Int;
- public var h : Int;
- public function new() {}
- public function init_tiles_to_size(w:Int, h:Int) {
- this.w = w;
- this.h = h;
- tiles_indexed = [];
- tiles_array = [];
- for (i in 0...w) {
- var row : Array<Tile> = [];
- for (j in 0...h) {
- var tile = new Tile();
- var pos = new Vector();
- tile.i = i;
- tile.j = j;
- tiles_array.push(tile);
- row.push(tile);
- }
- tiles_indexed.push(row);
- }
- for (tile in tiles_array) {
- var i : Int = tile.i;
- var j : Int = tile.j;
- var geom = new Sprite({
- name: '$i,$j}',
- });
- tile.geom = geom;
- }
- }
- public function get_tile_at_pos(pos:Vector):Tile {
- for (tile in tiles_array) {
- if (tile.geom.point_inside(pos)) return tile;
- }
- return null;
- }
- public function get_tile_at_index(i:Int, j:Int):Tile {
- if (i < 0 || j < 0) return null;
- if (i > w - 1 || j > h - 1) return null;
- var row : Array<Tile> = tiles_indexed[i];
- return row[j];
- }
- public function get_tile_at_offset(tile:Tile, di:Int, dj:Int) {
- return get_tile_at_index(tile.i + di, tile.j + dj);
- }
- public function get_dist_between_tiles(a:Tile, b:Tile):Float {
- var dist : Float = Math.sqrt((a.i - b.i)^2 + (a.j - b.j)^2);
- return dist;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement