var core = use('core') var camera = use('camera') var compositor = use('compositor') var input = use('input') var shape = use('shape2d') var text2d = use('text2d') var GW = 480, GH = 270 var paddleW = 8, paddleH = 50, speed = 200 var ballSize = 8 var bvx = 220, bvy = 150 var score1 = 0, score2 = 0 // Cameras: game at pixel-art res, HUD at native var game_cam = camera.make({width: GW, height: GH, pos: {x: GW / 2, y: GH / 2}}) var hud_cam = camera.make({width: 960, height: 540, pos: {x: 480, y: 270}}) // Action mapping input.configure({ action_map: { p1_up: ['w'], p1_down: ['s'], p2_up: ['up'], p2_down: ['down'] } }) // Retained shapes — game plane var midline = shape.rect({ pos: {x: GW / 2, y: GH / 2}, width: 2, height: GH, fill: {r: 0.3, g: 0.3, b: 0.3, a: 1}, plane: 'game' }) var p1 = shape.rect({ pos: {x: 20, y: GH / 2}, width: paddleW, height: paddleH, fill: {r: 1, g: 1, b: 1, a: 1}, plane: 'game' }) var p2 = shape.rect({ pos: {x: GW - 20, y: GH / 2}, width: paddleW, height: paddleH, fill: {r: 1, g: 1, b: 1, a: 1}, plane: 'game' }) var ball = shape.rect({ pos: {x: GW / 2, y: GH / 2}, width: ballSize, height: ballSize, fill: {r: 1, g: 1, b: 1, a: 1}, plane: 'game', groups: ['glow'] }) // HUD plane — score text var score_label = text2d({ text: "0 0", pos: {x: 420, y: 490}, plane: 'hud', size: 32, color: {r: 1, g: 1, b: 1, a: 1} }) function reset_ball() { ball.pos.x = GW / 2 ball.pos.y = GH / 2 bvy = (bvy > 0 ? -1 : 1) * 150 bvx = bvx > 0 ? -220 : 220 } // Compositor: game plane with bloom on ball, HUD overlay var comp_config = { clear: {r: 0, g: 0, b: 0, a: 1}, planes: [ {name: 'game', camera: game_cam, resolution: {width: GW, height: GH}, presentation: 'letterbox'}, {name: 'hud', camera: hud_cam, resolution: {width: 960, height: 540}, presentation: 'stretch'} ], group_effects: { glow: {effects: [{type: 'bloom', threshold: 0.3, intensity: 2}]} } } core.start({ width: 960, height: 540, title: "Pong", update: function(dt) { var down = input.player1().down() // Move paddles if (down.p1_up) p1.pos.y += speed * dt if (down.p1_down) p1.pos.y -= speed * dt if (down.p2_up) p2.pos.y += speed * dt if (down.p2_down) p2.pos.y -= speed * dt // Clamp paddles var hh = paddleH / 2 if (p1.pos.y < hh) p1.pos.y = hh if (p1.pos.y > GH - hh) p1.pos.y = GH - hh if (p2.pos.y < hh) p2.pos.y = hh if (p2.pos.y > GH - hh) p2.pos.y = GH - hh // Move ball ball.pos.x += bvx * dt ball.pos.y += bvy * dt // Bounce top/bottom var bs = ballSize / 2 if (ball.pos.y - bs < 0 || ball.pos.y + bs > GH) bvy = -bvy // Paddle collisions var bx = ball.pos.x, by = ball.pos.y var pw = paddleW / 2, ph = paddleH / 2 if (bx - bs < p1.pos.x + pw && bx + bs > p1.pos.x - pw && by + bs > p1.pos.y - ph && by - bs < p1.pos.y + ph) bvx = abs(bvx) if (bx + bs > p2.pos.x - pw && bx - bs < p2.pos.x + pw && by + bs > p2.pos.y - ph && by - bs < p2.pos.y + ph) bvx = -abs(bvx) // Scoring if (bx < 0) { score2++ score_label.text = score1 + " " + score2 reset_ball() } if (bx > GW) { score1++ score_label.text = score1 + " " + score2 reset_ball() } }, render: function() { return compositor.execute(compositor.compile(comp_config)) } })