var core = use('core') var camera = use('camera') var compositor = use('compositor') var input = use('input') var shape = use('shape2d') var sprite_factory = use('sprite') var text2d = use('text2d') var Grid = use('grid') var MovementSystem = use('movement').MovementSystem var startingPos = use('pieces').startingPosition var rules = use('rules') var S = 60 var GW = S * 8, GH = S * 8 var game_cam = camera.make({width: GW, height: GH, pos: {x: GW / 2, y: GH / 2}}) var hud_cam = camera.make({width: GW, height: GH, pos: {x: GW / 2, y: GH / 2}}) input.configure({ action_map: { select: ['mouse_button_left'], cancel: ['escape', 'mouse_button_right'] } }) // Build board var grid = Grid(8, 8) grid.width = 8 grid.height = 8 var mover = MovementSystem(grid, rules) startingPos(grid) // Board squares (shape2d) var light_color = {r: 0.93, g: 0.93, b: 0.85, a: 1} var dark_color = {r: 0.45, g: 0.55, b: 0.35, a: 1} var select_color = {r: 1, g: 0.84, b: 0, a: 1} var valid_color = {r: 0.6, g: 0.8, b: 0.4, a: 1} var board_shapes = [] var bx = 0, by = 0 for (by = 0; by < 8; by++) { var row = [] for (bx = 0; bx < 8; bx++) { var col = ((bx + by) & 1) ? dark_color : light_color push(row, shape.rect({ pos: {x: bx * S + S / 2, y: by * S + S / 2}, width: S, height: S, fill: {r: col.r, g: col.g, b: col.b, a: col.a}, plane: 'game', layer: 0 })) } push(board_shapes, row) } // Piece sprites — one per piece, keyed by piece object var piece_sprites = {} var piece_id = 0 grid.each(function(p) { piece_id++ p._id = piece_id piece_sprites[piece_id] = sprite_factory({ image: p.sprite, pos: {x: p.coord[0] * S + S / 2, y: p.coord[1] * S + S / 2}, width: S, height: S, anchor_x: 0.5, anchor_y: 0.5, plane: 'game', layer: 1 }) }) // Selection state var selectPos = null var validMoves = [] // Mouse position in grid coords var hover_gx = -1, hover_gy = -1 // Status text var status_label = text2d({ text: "White's turn", pos: {x: 10, y: GH - 20}, plane: 'hud', size: 14, color: {r: 1, g: 1, b: 1, a: 1} }) function update_status() { status_label.text = mover.turn + "'s turn" } function reset_board_colors() { var x = 0, y = 0 for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) { var col = ((x + y) & 1) ? dark_color : light_color board_shapes[y][x].fill = {r: col.r, g: col.g, b: col.b, a: col.a} } } } function highlight_selection() { reset_board_colors() if (!selectPos) return // Highlight selected square board_shapes[selectPos[1]][selectPos[0]].fill = { r: select_color.r, g: select_color.g, b: select_color.b, a: select_color.a } // Highlight valid moves var i = 0 for (i = 0; i < length(validMoves); i++) { var m = validMoves[i] board_shapes[m[1]][m[0]].fill = { r: valid_color.r, g: valid_color.g, b: valid_color.b, a: valid_color.a } } } function compute_valid_moves(from) { validMoves = [] var piece = grid.at(from)[0] if (!piece) return var x = 0, y = 0, to = null, dest = null for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) { to = [x, y] dest = grid.at(to) if (length(dest) && dest[0].colour == piece.colour) continue if (rules.canMove(piece, from, to, grid)) push(validMoves, to) } } } function sync_piece_sprites() { grid.each(function(p) { var spr = piece_sprites[p._id] if (!spr) return if (p.captured) { spr.visible = false } else { spr.pos.x = p.coord[0] * S + S / 2 spr.pos.y = p.coord[1] * S + S / 2 spr.visible = true } }) } // Input handler var game_input = { on_input: function(action, data) { if (!data.pressed) return if (action == 'cancel') { selectPos = null validMoves = [] highlight_selection() return } if (action == 'select' && hover_gx >= 0 && hover_gx < 8 && hover_gy >= 0 && hover_gy < 8) { var clicked = [hover_gx, hover_gy] var cell = grid.at(clicked) if (selectPos) { // Try to move var is_valid = false var i = 0 for (i = 0; i < length(validMoves); i++) { if (validMoves[i][0] == clicked[0] && validMoves[i][1] == clicked[1]) { is_valid = true break } } if (is_valid) { var src_piece = grid.at(selectPos)[0] if (src_piece && mover.tryMove(src_piece, clicked)) { sync_piece_sprites() update_status() } selectPos = null validMoves = [] } else if (length(cell) && cell[0].colour == mover.turn) { // Select different piece selectPos = clicked compute_valid_moves(selectPos) } else { selectPos = null validMoves = [] } } else { // Select piece if (length(cell) && cell[0].colour == mover.turn) { selectPos = clicked compute_valid_moves(selectPos) } } highlight_selection() } } } input.player1().possess(game_input) var comp_config = { clear: {r: 0.15, g: 0.15, b: 0.2, a: 1}, planes: [ {name: 'game', camera: game_cam, resolution: {width: GW, height: GH}, presentation: 'letterbox'}, {name: 'hud', camera: hud_cam, resolution: {width: GW, height: GH}, presentation: 'stretch'} ] } core.start({ width: 640, height: 640, title: "Chess", input: function(ev) { if (ev.type == 'mouse_motion') { // Convert pixel coords to grid coords via camera var wp = game_cam.window_to_world(ev.pos.x, ev.pos.y) if (wp) { hover_gx = floor(wp.x / S) hover_gy = floor(wp.y / S) } } }, update: function(dt) { }, render: function() { return compositor.execute(compositor.compile(comp_config)) } })