luanette 0.0.0-stage → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +19 -2
- package/api.json +1 -0
- package/engine/luanette-node.js +0 -0
- package/lib/gif.js +103 -0
- package/lib/tables.js +67 -0
- package/luanette.mjs +456 -0
- package/mcp.mjs +175 -0
- package/package.json +11 -4
- package/pyrandom.mjs +50 -0
- package/templates/blank.lua +45 -0
- package/templates/platformer.lua +95 -0
- package/templates/puzzle.lua +96 -0
- package/templates/shooter.lua +108 -0
package/pyrandom.mjs
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Python's random.Random(seed).random(), exactly: the Mersenne Twister, seeded as Python seeds it
|
|
2
|
+
// from an int (init_by_array). check.py's scripted input draws taps from it, and the command-line
|
|
3
|
+
// tool feeds a cart the same input.
|
|
4
|
+
export function pyRandom(seed) {
|
|
5
|
+
const N = 624, mt = new Uint32Array(N);
|
|
6
|
+
let mti = N + 1;
|
|
7
|
+
const init = (s) => {
|
|
8
|
+
mt[0] = s >>> 0;
|
|
9
|
+
for (mti = 1; mti < N; mti++) {
|
|
10
|
+
const p = mt[mti - 1] ^ (mt[mti - 1] >>> 30);
|
|
11
|
+
mt[mti] = (Math.imul(1812433253, p) + mti) >>> 0;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
init(19650218);
|
|
15
|
+
const key = [seed >>> 0];
|
|
16
|
+
let i = 1, j = 0;
|
|
17
|
+
for (let k = Math.max(N, key.length); k; k--) {
|
|
18
|
+
const p = mt[i - 1] ^ (mt[i - 1] >>> 30);
|
|
19
|
+
mt[i] = ((mt[i] ^ Math.imul(p, 1664525)) + key[j] + j) >>> 0;
|
|
20
|
+
i++; j++;
|
|
21
|
+
if (i >= N) { mt[0] = mt[N - 1]; i = 1; }
|
|
22
|
+
if (j >= key.length) j = 0;
|
|
23
|
+
}
|
|
24
|
+
for (let k = N - 1; k; k--) {
|
|
25
|
+
const p = mt[i - 1] ^ (mt[i - 1] >>> 30);
|
|
26
|
+
mt[i] = ((mt[i] ^ Math.imul(p, 1566083941)) - i) >>> 0;
|
|
27
|
+
i++;
|
|
28
|
+
if (i >= N) { mt[0] = mt[N - 1]; i = 1; }
|
|
29
|
+
}
|
|
30
|
+
mt[0] = 0x80000000;
|
|
31
|
+
const next = () => {
|
|
32
|
+
if (mti >= N) {
|
|
33
|
+
for (let kk = 0; kk < N; kk++) {
|
|
34
|
+
const y = (mt[kk] & 0x80000000) | (mt[(kk + 1) % N] & 0x7fffffff);
|
|
35
|
+
mt[kk] = mt[(kk + 397) % N] ^ (y >>> 1) ^ (y & 1 ? 0x9908b0df : 0);
|
|
36
|
+
}
|
|
37
|
+
mti = 0;
|
|
38
|
+
}
|
|
39
|
+
let y = mt[mti++];
|
|
40
|
+
y ^= y >>> 11;
|
|
41
|
+
y ^= (y << 7) & 0x9d2c5680;
|
|
42
|
+
y ^= (y << 15) & 0xefc60000;
|
|
43
|
+
y ^= y >>> 18;
|
|
44
|
+
return y >>> 0;
|
|
45
|
+
};
|
|
46
|
+
return () => {
|
|
47
|
+
const a = next() >>> 5, b = next() >>> 6;
|
|
48
|
+
return (a * 67108864 + b) / 9007199254740992;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
-- title: Blank
|
|
2
|
+
-- by: you
|
|
3
|
+
-- about: a sprite to move: a place to start
|
|
4
|
+
-- api: 4
|
|
5
|
+
-- canvas: full
|
|
6
|
+
|
|
7
|
+
-- sprites (the playground's sprite editor writes this table)
|
|
8
|
+
SPRITES = {
|
|
9
|
+
[1] = "00777700 07777770 77177177 77777777 77777777 77177177 07711770 00777700", -- face
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
-- The whole screen: the 128x128 picture in the middle, and bands above and below it in the
|
|
13
|
+
-- full-color layer (hd) for the title and what to do. Drawn once; they stay.
|
|
14
|
+
local c = caps()
|
|
15
|
+
local W, H = c.w, c.h
|
|
16
|
+
local TOP, BOT = c.picture_y, c.picture_y + 384
|
|
17
|
+
|
|
18
|
+
local function bands(title, hint)
|
|
19
|
+
hd.scanlines(false)
|
|
20
|
+
hd.gradient(0, 0, W, TOP, 0x1b2440, 0x000000)
|
|
21
|
+
hd.text(title, W / 2, TOP / 2 - 16, 0xffffff, 24, "bold", "center")
|
|
22
|
+
hd.gradient(0, BOT, W, H - BOT, 0x000000, 0x1b2440)
|
|
23
|
+
hd.text(hint, W / 2, BOT + 22, 0x9aa4b8, 14, "mono", "center")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
local x, y = 60, 60 -- the sprite's top left, in picture pixels (0 to 127)
|
|
27
|
+
|
|
28
|
+
function _init()
|
|
29
|
+
fps(60, 10) -- 60 while touched, 10 when nothing moves: a still screen costs nothing
|
|
30
|
+
bands("BLANK", "drag or arrow keys to move")
|
|
31
|
+
log("started") -- shows in the playground's Console
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
function _update()
|
|
35
|
+
if btn(0) then x = x - 1 end
|
|
36
|
+
if btn(1) then x = x + 1 end
|
|
37
|
+
if btn(2) then y = y - 1 end
|
|
38
|
+
if btn(3) then y = y + 1 end
|
|
39
|
+
x, y = mid(0, x, 120), mid(0, y, 120)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
function _draw()
|
|
43
|
+
cls(1)
|
|
44
|
+
spr(1, x, y)
|
|
45
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
-- title: Platformer
|
|
2
|
+
-- by: you
|
|
3
|
+
-- about: jump between platforms and pick up the coins
|
|
4
|
+
-- api: 4
|
|
5
|
+
-- canvas: full
|
|
6
|
+
|
|
7
|
+
-- sprites (the playground's sprite editor writes this table)
|
|
8
|
+
SPRITES = {
|
|
9
|
+
[1] = "00888800 08888880 08f1f180 08ffff80 00888800 08888880 08800880 08800880", -- player
|
|
10
|
+
[2] = "00aaaa00 0aa99aa0 aa9aa9aa aa9aa9aa aa9aa9aa aa9aa9aa 0aa99aa0 00aaaa00", -- coin
|
|
11
|
+
}
|
|
12
|
+
-- sounds (the playground's sound editor writes this table)
|
|
13
|
+
SOUNDS = {
|
|
14
|
+
[8] = "03 0000 18050 1f051 24045", -- jump
|
|
15
|
+
[9] = "03 0000 2f160 34165", -- coin
|
|
16
|
+
[10] = "06 0000 1f050 18053", -- fall
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
-- The whole screen: the 128x128 picture in the middle, and bands above and below it in the
|
|
20
|
+
-- full-color layer (hd) for the title and what to do. Drawn once; they stay.
|
|
21
|
+
local c = caps()
|
|
22
|
+
local W, H = c.w, c.h
|
|
23
|
+
local TOP, BOT = c.picture_y, c.picture_y + 384
|
|
24
|
+
|
|
25
|
+
local function bands(title, hint)
|
|
26
|
+
hd.scanlines(false)
|
|
27
|
+
hd.gradient(0, 0, W, TOP, 0x1b2440, 0x000000)
|
|
28
|
+
hd.text(title, W / 2, TOP / 2 - 16, 0xffffff, 24, "bold", "center")
|
|
29
|
+
hd.gradient(0, BOT, W, H - BOT, 0x000000, 0x1b2440)
|
|
30
|
+
hd.text(hint, W / 2, BOT + 22, 0x9aa4b8, 14, "mono", "center")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
local GRAVITY, JUMP, SPEED = 0.25, -3.6, 1.4
|
|
34
|
+
local floors = { -- platforms: x, y (their top), w
|
|
35
|
+
{x = 0, y = 120, w = 128}, {x = 12, y = 96, w = 36}, {x = 72, y = 80, w = 40},
|
|
36
|
+
{x = 24, y = 58, w = 32}, {x = 80, y = 40, w = 36},
|
|
37
|
+
}
|
|
38
|
+
local me = {x = 8, y = 100, vx = 0, vy = 0, ground = false}
|
|
39
|
+
local coins, score, level = {}, 0, 1
|
|
40
|
+
|
|
41
|
+
local function new_coins()
|
|
42
|
+
coins = {}
|
|
43
|
+
for i = 2, #floors do
|
|
44
|
+
local f = floors[i]
|
|
45
|
+
coins[#coins + 1] = {x = f.x + flr(rnd(f.w - 8)), y = f.y - 12}
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
function _init()
|
|
50
|
+
bands("PLATFORMER", "drag to run · tap to jump")
|
|
51
|
+
new_coins()
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
function _update()
|
|
55
|
+
me.vx = (btn(0) and -SPEED or 0) + (btn(1) and SPEED or 0)
|
|
56
|
+
if btnp(4) and me.ground then
|
|
57
|
+
me.vy = JUMP
|
|
58
|
+
sfx(8)
|
|
59
|
+
end
|
|
60
|
+
me.vy = me.vy + GRAVITY
|
|
61
|
+
local was = me.y
|
|
62
|
+
me.x = mid(0, me.x + me.vx, 120)
|
|
63
|
+
me.y = me.y + me.vy
|
|
64
|
+
me.ground = false
|
|
65
|
+
for _, f in ipairs(floors) do -- land on a platform's top on the way down
|
|
66
|
+
if me.vy >= 0 and was + 8 <= f.y and me.y + 8 >= f.y and me.x + 6 > f.x and me.x + 2 < f.x + f.w then
|
|
67
|
+
me.y, me.vy, me.ground = f.y - 8, 0, true
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
for i = #coins, 1, -1 do
|
|
71
|
+
local k = coins[i]
|
|
72
|
+
if abs(me.x - k.x) < 7 and abs(me.y - k.y) < 7 then
|
|
73
|
+
table.remove(coins, i)
|
|
74
|
+
score = score + 1
|
|
75
|
+
sfx(9)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
if #coins == 0 then
|
|
79
|
+
level = level + 1
|
|
80
|
+
log("level", level, "score", score)
|
|
81
|
+
new_coins()
|
|
82
|
+
end
|
|
83
|
+
if me.y > 128 then -- fell off: back to the start
|
|
84
|
+
me.x, me.y, me.vy = 8, 100, 0
|
|
85
|
+
sfx(10)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
function _draw()
|
|
90
|
+
cls(12)
|
|
91
|
+
for _, f in ipairs(floors) do rectfill(f.x, f.y, f.x + f.w - 1, f.y + 3, 3) end
|
|
92
|
+
for _, k in ipairs(coins) do spr(2, k.x, k.y) end
|
|
93
|
+
spr(1, me.x, me.y, me.vx < 0)
|
|
94
|
+
print("score " .. score, 2, 2, 7)
|
|
95
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
-- title: Puzzle
|
|
2
|
+
-- by: you
|
|
3
|
+
-- about: lights out: switch every light off
|
|
4
|
+
-- api: 4
|
|
5
|
+
-- canvas: full
|
|
6
|
+
|
|
7
|
+
-- sprites (the playground's sprite editor writes this table)
|
|
8
|
+
SPRITES = {
|
|
9
|
+
[1] = "000a0000 000a0000 0aaaaa00 00aaa000 00a0a000 0a000a00 00000000 00000000", -- star
|
|
10
|
+
}
|
|
11
|
+
-- sounds (the playground's sound editor writes this table)
|
|
12
|
+
SOUNDS = {
|
|
13
|
+
[8] = "02 0000 28345", -- click
|
|
14
|
+
[9] = "06 0000 24150 28150 2b150 30155", -- solved
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
-- The whole screen: the 128x128 picture in the middle, and bands above and below it in the
|
|
18
|
+
-- full-color layer (hd) for the title and what to do. Drawn once; they stay.
|
|
19
|
+
local c = caps()
|
|
20
|
+
local W, H = c.w, c.h
|
|
21
|
+
local TOP, BOT = c.picture_y, c.picture_y + 384
|
|
22
|
+
|
|
23
|
+
local function bands(title, hint)
|
|
24
|
+
hd.scanlines(false)
|
|
25
|
+
hd.gradient(0, 0, W, TOP, 0x1b2440, 0x000000)
|
|
26
|
+
hd.text(title, W / 2, TOP / 2 - 16, 0xffffff, 24, "bold", "center")
|
|
27
|
+
hd.gradient(0, BOT, W, H - BOT, 0x000000, 0x1b2440)
|
|
28
|
+
hd.text(hint, W / 2, BOT + 22, 0x9aa4b8, 14, "mono", "center")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
-- Lights out: switching a light switches the four next to it too. Get them all off.
|
|
32
|
+
local N, CELL, X0, Y0 = 5, 22, 9, 14
|
|
33
|
+
local lit, cx, cy, moves, solved = {}, 3, 3, 0, false
|
|
34
|
+
local was_touching = false
|
|
35
|
+
|
|
36
|
+
local function flip(x, y)
|
|
37
|
+
for _, d in ipairs({{0, 0}, {1, 0}, {-1, 0}, {0, 1}, {0, -1}}) do
|
|
38
|
+
local i, j = x + d[1], y + d[2]
|
|
39
|
+
if i >= 1 and i <= N and j >= 1 and j <= N then lit[j][i] = not lit[j][i] end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
local function new_puzzle() -- from all off, a few random presses: always solvable
|
|
44
|
+
for j = 1, N do lit[j] = {} for i = 1, N do lit[j][i] = false end end
|
|
45
|
+
for _ = 1, 8 do flip(flr(rnd(N)) + 1, flr(rnd(N)) + 1) end
|
|
46
|
+
moves, solved = 0, false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
function _init()
|
|
50
|
+
fps(60, 10) -- 60 while touched, 10 when nothing moves
|
|
51
|
+
bands("PUZZLE", "tap a light · switch them all off")
|
|
52
|
+
new_puzzle()
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
function _update()
|
|
56
|
+
local tx, ty = touch()
|
|
57
|
+
if tx then -- a finger: the cursor goes where it is (a tap then presses, as A)
|
|
58
|
+
cx = mid(1, flr((tx - X0) / CELL) + 1, N)
|
|
59
|
+
cy = mid(1, flr((ty - Y0) / CELL) + 1, N)
|
|
60
|
+
elseif not was_touching then
|
|
61
|
+
if btnp(0) then cx = mid(1, cx - 1, N) end
|
|
62
|
+
if btnp(1) then cx = mid(1, cx + 1, N) end
|
|
63
|
+
if btnp(2) then cy = mid(1, cy - 1, N) end
|
|
64
|
+
if btnp(3) then cy = mid(1, cy + 1, N) end
|
|
65
|
+
end
|
|
66
|
+
was_touching = tx ~= nil
|
|
67
|
+
if btnp(4) then
|
|
68
|
+
if solved then new_puzzle() return end
|
|
69
|
+
flip(cx, cy)
|
|
70
|
+
moves = moves + 1
|
|
71
|
+
sfx(8)
|
|
72
|
+
local any = false
|
|
73
|
+
for j = 1, N do for i = 1, N do any = any or lit[j][i] end end
|
|
74
|
+
if not any then
|
|
75
|
+
solved = true
|
|
76
|
+
sfx(9)
|
|
77
|
+
log("solved in", moves, "moves")
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
function _draw()
|
|
83
|
+
cls(1)
|
|
84
|
+
for j = 1, N do
|
|
85
|
+
for i = 1, N do
|
|
86
|
+
local x, y = X0 + (i - 1) * CELL, Y0 + (j - 1) * CELL
|
|
87
|
+
rectfill(x + 1, y + 1, x + CELL - 2, y + CELL - 2, lit[j][i] and 10 or 5)
|
|
88
|
+
if i == cx and j == cy then rect(x, y, x + CELL - 1, y + CELL - 1, 7) end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
print("moves " .. moves, 2, 2, 7)
|
|
92
|
+
if solved then
|
|
93
|
+
spr(1, 56, 4)
|
|
94
|
+
print("solved: tap for another", 18, 122, 11)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
-- title: Shooter
|
|
2
|
+
-- by: you
|
|
3
|
+
-- about: steer the ship; it fires on its own
|
|
4
|
+
-- api: 4
|
|
5
|
+
-- canvas: full
|
|
6
|
+
|
|
7
|
+
-- sprites (the playground's sprite editor writes this table)
|
|
8
|
+
SPRITES = {
|
|
9
|
+
[1] = "00077000 00077000 0077c700 007cc700 077cc770 77777777 78077087 80000008", -- ship
|
|
10
|
+
[2] = "08000080 00800800 08888880 88188188 88888888 08088080 80000008 08000080", -- invader
|
|
11
|
+
}
|
|
12
|
+
-- sounds (the playground's sound editor writes this table)
|
|
13
|
+
SOUNDS = {
|
|
14
|
+
[8] = "01 0000 30223", -- shot
|
|
15
|
+
[9] = "04 0000 18770 0c755", -- boom
|
|
16
|
+
[10] = "06 0000 10460 0c455", -- hurt
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
-- The whole screen: the 128x128 picture in the middle, and bands above and below it in the
|
|
20
|
+
-- full-color layer (hd) for the title and what to do. Drawn once; they stay.
|
|
21
|
+
local c = caps()
|
|
22
|
+
local W, H = c.w, c.h
|
|
23
|
+
local TOP, BOT = c.picture_y, c.picture_y + 384
|
|
24
|
+
|
|
25
|
+
local function bands(title, hint)
|
|
26
|
+
hd.scanlines(false)
|
|
27
|
+
hd.gradient(0, 0, W, TOP, 0x1b2440, 0x000000)
|
|
28
|
+
hd.text(title, W / 2, TOP / 2 - 16, 0xffffff, 24, "bold", "center")
|
|
29
|
+
hd.gradient(0, BOT, W, H - BOT, 0x000000, 0x1b2440)
|
|
30
|
+
hd.text(hint, W / 2, BOT + 22, 0x9aa4b8, 14, "mono", "center")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
local ship = {x = 60}
|
|
34
|
+
local shots, foes, sparks = {}, {}, {}
|
|
35
|
+
local score, lives, t = 0, 3, 0
|
|
36
|
+
|
|
37
|
+
function _init()
|
|
38
|
+
bands("SHOOTER", "drag to steer · tap to start again")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
local function hit(f) -- an enemy goes up in sparks
|
|
42
|
+
for i = 1, 8 do
|
|
43
|
+
sparks[#sparks + 1] = {x = f.x + 4, y = f.y + 4, vx = rnd(2) - 1, vy = rnd(2) - 1, life = 15}
|
|
44
|
+
end
|
|
45
|
+
sfx(9)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
function _update()
|
|
49
|
+
t = t + 1
|
|
50
|
+
if lives == 0 then
|
|
51
|
+
if btnp(4) then score, lives, foes, shots = 0, 3, {}, {} end
|
|
52
|
+
return
|
|
53
|
+
end
|
|
54
|
+
local tx = touch()
|
|
55
|
+
if tx then ship.x = tx - 4 end
|
|
56
|
+
if btn(0) then ship.x = ship.x - 2 end
|
|
57
|
+
if btn(1) then ship.x = ship.x + 2 end
|
|
58
|
+
ship.x = mid(0, ship.x, 120)
|
|
59
|
+
if t % 8 == 0 then
|
|
60
|
+
shots[#shots + 1] = {x = ship.x + 3, y = 112}
|
|
61
|
+
sfx(8)
|
|
62
|
+
end
|
|
63
|
+
if t % 30 == 0 then foes[#foes + 1] = {x = flr(rnd(120)), y = -8, phase = rnd(1)} end
|
|
64
|
+
for i = #shots, 1, -1 do
|
|
65
|
+
local s = shots[i]
|
|
66
|
+
s.y = s.y - 4
|
|
67
|
+
if s.y < -4 then table.remove(shots, i) end
|
|
68
|
+
end
|
|
69
|
+
for i = #foes, 1, -1 do
|
|
70
|
+
local f = foes[i]
|
|
71
|
+
f.y = f.y + 0.6 + score / 200
|
|
72
|
+
f.x = f.x + sin(t / 60 + f.phase) * 0.5
|
|
73
|
+
local gone = false
|
|
74
|
+
for j = #shots, 1, -1 do
|
|
75
|
+
local s = shots[j]
|
|
76
|
+
if s.x >= f.x and s.x <= f.x + 7 and s.y >= f.y and s.y <= f.y + 7 then
|
|
77
|
+
table.remove(shots, j)
|
|
78
|
+
hit(f)
|
|
79
|
+
score = score + 1
|
|
80
|
+
gone = true
|
|
81
|
+
break
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
if not gone and (f.y > 128 or (f.y > 108 and abs(f.x - ship.x) < 7)) then
|
|
85
|
+
lives = lives - 1
|
|
86
|
+
sfx(10)
|
|
87
|
+
log("lost a life at score", score)
|
|
88
|
+
gone = true
|
|
89
|
+
end
|
|
90
|
+
if gone then table.remove(foes, i) end
|
|
91
|
+
end
|
|
92
|
+
for i = #sparks, 1, -1 do
|
|
93
|
+
local p = sparks[i]
|
|
94
|
+
p.x, p.y, p.life = p.x + p.vx, p.y + p.vy, p.life - 1
|
|
95
|
+
if p.life <= 0 then table.remove(sparks, i) end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
function _draw()
|
|
100
|
+
cls(0)
|
|
101
|
+
for _, s in ipairs(shots) do rectfill(s.x, s.y, s.x + 1, s.y + 3, 10) end
|
|
102
|
+
for _, f in ipairs(foes) do spr(2, f.x, f.y) end
|
|
103
|
+
for _, p in ipairs(sparks) do pset(p.x, p.y, p.life > 8 and 10 or 9) end
|
|
104
|
+
if lives > 0 then spr(1, ship.x, 116) end
|
|
105
|
+
print("score " .. score, 2, 2, 7)
|
|
106
|
+
print("lives " .. lives, 96, 2, 8)
|
|
107
|
+
if lives == 0 then print("game over: tap", 36, 60, 7) end
|
|
108
|
+
end
|