TalentJR apps
Penalty shootout! Aim with ← →, kick with SPACE — beat the goalkeeper and score 3 goals from 5 shots. Play it first, then open it in the Game Studio and change it until it is your own game.
🎮 Controls: ← → to aim · SPACE to kick
At the top of the code are the settings — change one, run the game, and feel the difference. This is how game designers balance a game.
let keeperSpeed = 200 | How fast the goalkeeper moves |
let shotSpeed = 520 | How hard you kick the ball |
let goalWidth = 300 | How wide the goal is |
let shots = 5 | Penalties you take |
let goalsToWin = 3 | Goals you need to win |
let aimSpeed = 260 | How fast the aim moves with ← → |
let keeperColor = [37, 99, 235] |
Try them in order. The studio ticks each one off when your change works — and shows a hint if it does not.
let keeperSpeed = 120let shotSpeed = 700let goalWidth = 380let shots = 8let goalsToWin = 4let aimSpeed = 400let keeperColor = [220, 38, 38]111 lines of real JavaScript, made with TalentJR Game Studio's game library. Lines that start with // explain what the next part does.
// ⚽ Football — Penalty shootout — TalentJR Game Studio
// ✏️ Change these numbers, then press ▶ Run!
let keeperSpeed = 200 // how fast the goalkeeper moves
let shotSpeed = 520 // how hard you kick the ball
let goalWidth = 300 // how wide the goal is
let shots = 5 // penalties you take
let goalsToWin = 3 // goals you need to win
let aimSpeed = 260 // how fast the aim moves with ← →
let keeperColor = [37, 99, 235]
tj.setup({ background: "grass" })
tj.touchControls("shooter")
// The goal: two posts, the crossbar and the net
const left = width() / 2 - goalWidth / 2
const right = width() / 2 + goalWidth / 2
add([rect(goalWidth, 60), pos(left, 40), color(226, 232, 240), opacity(0.5)])
add([rect(goalWidth + 8, 8), pos(left - 4, 36), color(255, 255, 255)])
add([rect(8, 68), pos(left - 4, 36), color(255, 255, 255)])
add([rect(8, 68), pos(right - 4, 36), color(255, 255, 255)])
add([rect(width(), 4), pos(0, 100), color(255, 255, 255)])
// The goalkeeper (a robot in a blue shirt) walks along the goal line
const keeper = add([sprite("robot"), pos(width() / 2 - 24, 54), scale(0.75), color(...keeperColor), area(), "keeper"])
let keeperDir = 1
// You, the ball and your aim (the yellow dot in the goal)
add([sprite("robot"), pos(296, 410), scale(0.75)])
const ball = add([circle(10), pos(320, 398), color(255, 255, 255), outline(2), area(), "ball"])
const aim = add([circle(9), pos(320, 70), color(250, 204, 21), opacity(0.9)])
let vel = vec2(0, 0)
let kicked = false
// Goals, shots left
const score = tj.score()
let shotsLeft = shots
const info = add([text("", { size: 20 }), pos(width() - 12, 14), anchor("topright"), color(30, 41, 59)])
function showInfo() {
info.text = "Goals needed " + goalsToWin + " · Shots left " + shotsLeft
}
showInfo()
// ← → move your aim (you can aim outside the posts too — that's a miss!)
onUpdate(() => {
if (kicked) return
if (tj.isDown("left")) aim.pos.x = aim.pos.x - aimSpeed * dt()
if (tj.isDown("right")) aim.pos.x = aim.pos.x + aimSpeed * dt()
aim.pos.x = Math.max(left - 60, Math.min(right + 60, aim.pos.x))
})
// SPACE (or the A button): kick the ball towards your aim
tj.onAction("fire", () => {
if (kicked) return
kicked = true
vel = aim.pos.sub(ball.pos).unit().scale(shotSpeed)
tj.sound("pop")
})
// The keeper walks from post to post — after your kick, it dives towards the ball
keeper.onUpdate(() => {
const middle = keeper.pos.x + 24
if (kicked) {
if (ball.pos.x < middle) keeper.move(-keeperSpeed * 0.6, 0)
if (ball.pos.x > middle) keeper.move(keeperSpeed * 0.6, 0)
} else {
keeper.move(keeperDir * keeperSpeed * 0.6, 0)
if (middle > right - 30) keeperDir = -1
if (middle < left + 30) keeperDir = 1
}
})
// The ball flies: saved, goal or wide?
ball.onUpdate(() => {
if (!kicked) return
ball.pos = ball.pos.add(vel.scale(dt()))
if (ball.pos.y < 95) {
if (ball.pos.x > left && ball.pos.x < right) goal()
else result("Wide!")
}
})
ball.onCollide("keeper", () => {
if (kicked) result("SAVED!")
})
function goal() {
score.add(1)
tj.sound("coin")
result("GOAL!")
}
// After every shot: the next penalty — until you win or run out of shots
function result(words) {
kicked = false
vel = vec2(0, 0)
ball.pos = vec2(-100, -100) // out of the way until the next penalty
shotsLeft = shotsLeft - 1
showInfo()
add([text(words, { size: 56 }), pos(width() / 2, 220), anchor("center"), color(30, 41, 59), opacity(1), lifespan(1, { fade: 0.5 })])
if (score.value >= goalsToWin) {
tj.victory("Champion! You won the shootout")
return
}
if (shotsLeft <= 0 || score.value + shotsLeft < goalsToWin) {
tj.gameOver("Game over! " + score.value + " of " + goalsToWin + " goals")
return
}
wait(1.5, () => {
ball.pos = vec2(320, 398)
aim.pos = vec2(320, 70)
})
}
🏏 CricketTime your swing for a SIX, a FOUR or a run — and chase the target before you are all out.
🤼 KabaddiRaid on one breath: touch a defender and get back over the line before they catch you.
🎯 Slime BlasterGuard the fence: move the robot, blast the slimes marching in — big ones need 3 hits.
🏃 Coin Run — your first gameType your first game yourself in 7 short missions — every line explained.
🏎️ Retro RacingDodge the traffic on a scrolling road — change the speed, the cars and the road colour.
🧗 PlatformerRun, jump over spikes, collect coins and reach the flag — then build your own level.