Skip to content

Instantly share code, notes, and snippets.

@thykka
Last active September 9, 2020 12:32
Show Gist options
  • Select an option

  • Save thykka/d6813988ba7a22c2d9cfc6fdef4a5dad to your computer and use it in GitHub Desktop.

Select an option

Save thykka/d6813988ba7a22c2d9cfc6fdef4a5dad to your computer and use it in GitHub Desktop.
SCRIPT-8
{
"0": {
"0": {
"2": 0
},
"1": {
"3": 2
},
"tempo": "5"
},
"1": {
"0": {
"2": "1"
},
"tempo": "7"
}
}
// title: PePuSnek
const { sin, cos, PI } = Math
const ParticleSprites = range(17, 21)
const MaxParticleAge = 32
init = S => {
S.infoShown = !!S.infoShown
S.gameArea = {
x: 0,
y: 8,
w: 128,
h: 120
}
S.snek = {
x: S.gameArea.x,
y: S.gameArea.y + S.gameArea.h / 2,
angle: 0,
velocity: 1,
length: 16,
radius: 5.5,
drunk: 0,
burnRate: 2048,
turnSpeed: PI / 25,
tail: []
}
S.pepu = {
x: 110,
y: 68,
vx: 0,
vy: 0
}
S.lastAd = -1000
S.frame = 0
S.particles = [
// [x, y, color, vx, vy, birth]
]
}
update = (S, input, elapsed) => {
S.frame++
updateSnek(S, input)
}
function updateSnek(S, input) {
updatePepuPos(S)
collideSnek(S)
if (!S.snek.dead) {
controlSnek(S, input)
updateTail(S)
moveSnek(S)
} else {
if (input.start) {
init(S)
}
}
updateParticles(S)
}
function randomizePepuPos(S) {
S.pepu.x = random(S.gameArea.x + 4, S.gameArea.x + S.gameArea.w - 4)
S.pepu.y = random(S.gameArea.y + 4, S.gameArea.y + S.gameArea.h - 4)
S.pepu.vx = (Math.random() * 2 - 1) * Math.pow(S.snek.drunk, 3)
S.pepu.vy = (Math.random() * 2 - 1) * Math.pow(S.snek.drunk, 3)
S.pepu.flipH = Math.random() < 0.5
}
function createParticles(S, x, y, length = 8) {
S.particles.push(
...Array.from({ length }, (_, i) => {
return [
x,
y,
0,
Math.random() * 3 - 1.5,
Math.random() * -3,
S.frame - Math.random() * 5
]
})
)
}
function updatePepuPos(S) {
S.pepu.x += S.pepu.vx
S.pepu.y += S.pepu.vy
wrap(S.pepu, S.gameArea)
}
function updateParticles(S) {
S.particles.forEach((p, i) => {
p[4] += 0.2
p[0] += p[3]
p[1] += p[4]
})
S.particles = S.particles.filter(p => S.frame - p[5] < MaxParticleAge)
}
function collideSnek(S) {
if (S.snek.dead) return
const distToPepu = distance([S.pepu.x, S.pepu.y], [S.snek.x, S.snek.y])
if (distToPepu < S.snek.radius) {
playChain(0)
createParticles(S, S.pepu.x, S.pepu.y, 8)
S.lastAd = S.frame
S.snek.length *= 1.05
S.snek.length += 4
randomizePepuPos(S)
S.snek.drunk += 1 / 8
}
const collideTail = S.snek.tail
.slice(0, -S.snek.radius * 2) // ignore tail segments near head
.find(
([tx, ty]) => distance([tx, ty], [S.snek.x, S.snek.y]) < S.snek.radius
)
if (collideTail) {
createParticles(S, ...collideTail, 32)
playChain(1)
S.snek.dead = true
}
}
function distance([ax, ay], [bx, by]) {
const dx = ax - bx
const dy = ay - by
return Math.sqrt(dx * dx + dy * dy)
}
function controlSnek(S, input) {
if (input.right || input.b) {
S.infoShown = true
S.snek.angle = (S.snek.angle + S.snek.turnSpeed) % (PI * 2)
}
if (input.left) {
S.infoShown = true
S.snek.angle = (S.snek.angle - S.snek.turnSpeed) % (PI * 2)
}
const drunkOsc1 = Math.cos((S.frame / 60) * PI * 2) * S.snek.drunk
const drunkOsc2 = Math.sin((S.frame / 100) * PI * 2) * S.snek.drunk
const drunkOsc3 = Math.cos((S.frame / 150) * PI * 2 + PI / 2) * S.snek.drunk
S.snek.angle +=
S.snek.drunk *
clamp(drunkOsc1 * drunkOsc2 * drunkOsc3, 0 - PI / 90, PI / 90)
S.snek.drunk = clamp(S.snek.drunk - 1 / S.snek.burnRate, 0, 1)
}
function moveSnek(S) {
const { angle, velocity } = S.snek
S.snek.x +=
sin(angle + PI / 2) *
(velocity + velocity * Math.sin(S.frame / 30) * 0.3 * S.snek.drunk)
S.snek.y +=
-cos(angle + PI / 2) *
(velocity + velocity * Math.cos(-S.frame / 30) * 0.3 * S.snek.drunk)
wrap(S.snek, S.gameArea)
}
function updateTail(S) {
if (S.frame % 1 === 0) {
S.snek.tail.push([S.snek.x, S.snek.y])
if (S.snek.tail.length > S.snek.length) {
S.snek.tail.shift(0)
}
}
}
function wrap(subject, area) {
if (subject.x < area.x) subject.x += area.w
if (subject.x > area.x + area.w) subject.x -= area.w
if (subject.y < area.y) subject.y += area.h
if (subject.y > area.y + area.h) subject.y -= area.h
}
draw = S => {
const bgColor = S.frame - S.lastAd < 1 ? 4 : 6
if (S.snek.drunk < 0.9) {
clear(bgColor)
} else {
Math.random() < 1 / 20 && clear(bgColor)
}
drawAd(S)
drawSnek(S)
drawPepu(S)
drawParticles(S)
drawMask(S, 7)
drawUI(S)
}
function drawPepu(S) {
circStroke(
S.pepu.x - (S.pepu.flipH ? 0 : 1),
S.pepu.y,
((S.frame / 4) % S.snek.radius) * 2,
((S.frame / 4) % 4) + 2
)
sprite(S.pepu.x - 4, S.pepu.y - 4, 16, !(S.frame % 3) ? 0 : 1, S.pepu.flipH)
}
function drawSnek(S) {
let color = 0
if (S.snek.dead) {
color = 0 - (Math.floor(S.frame / 3) % 6)
}
const tr = 2.25
const ta = S.snek.angle + PI / 2;
const tx = S.snek.x + Math.sin(ta) * (tr + 4)
const ty = S.snek.y - Math.cos(ta) * (tr + 4)
const t1a = S.snek.angle + PI / 4
const t1x = tx + Math.sin(t1a) * tr
const t1y = ty - Math.cos(t1a) * tr
const t2a = S.snek.angle + PI / 4 * 3
const t2x = tx + Math.sin(t2a) * tr
const t2y = ty - Math.cos(t2a) * tr
line(S.snek.x, S.snek.y, tx, ty, 4)
line(tx, ty, t1x, t1y, 4)
line(tx, ty, t2x, t2y, 4)
S.snek.tail.forEach((t, i, tail) => drawTail(t, color, i, tail.length))
sprite(S.snek.x - 4, S.snek.y - 4, 0, color)
}
const SnekSprites = range(0, 6)
const TailTaper = SnekSprites.length
function drawTail([x, y], color, index, length) {
const spriteIndex = Math.round(
SnekSprites[TailTaper - 1] -
clamp(index / 3, SnekSprites[0], SnekSprites[TailTaper - 1])
)
sprite(x - 4, y - 4, spriteIndex, color - (index % 10 <= 1 ? 0 : 3))
}
function drawMask(S, color = 5) {
S.gameArea.y > 0 && rectFill(0, 0, 128, S.gameArea.y, color)
S.gameArea.x > 0 && rectFill(0, 0, S.gameArea.x, 128, color)
S.gameArea.x + S.gameArea.w < 128 &&
rectFill(
S.gameArea.x + S.gameArea.w,
0,
128 - (S.gameArea.x + S.gameArea.w),
128,
color
)
S.gameArea.y + S.gameArea.h < 128 &&
rectFill(
0,
S.gameArea.y + S.gameArea.h,
128,
128 - (S.gameArea.y + S.gameArea.h),
color
)
}
function drawUI(S) {
const bac = `Drunk: ${(((S.snek.drunk * S.snek.drunk * 60) | 0) / 10).toFixed(
1
)}`
print(86, 0, bac, S.snek.dead ? 6 : 0)
sprite(123, 0, 48, S.snek.dead ? -6 : 0)
if (!S.infoShown) {
print(16, 122, 'Move with [Left + Right / B]')
}
if (S.snek.dead) {
const assessment =
S.snek.length > 400
? '!! pepu god !!'
: S.snek.length > 256
? 'unbelievable!'
: S.snek.length > 192
? 'respectable!'
: S.snek.length > 128
? 'hey, not bad!'
: S.snek.length > 96
? 'one more try!'
: S.snek.length > 64
? 'you can do better!'
: S.snek.length > 48
? 'whoops!'
: 'how???'
print(45, 48, 'Game over!')
print(27, 92, `Final length: ${S.snek.length | 0}cm`)
print(64 - assessment.length * 1.816, 99, assessment)
print(9, 122, 'Press start/enter to restart', 7)
}
}
function drawParticles(S) {
S.particles.forEach(p => {
const age = (S.frame - p[5]) / MaxParticleAge
const spriteIndex = (age * ParticleSprites.length) | 0
sprite(p[0] - 3, p[1] - 3, ParticleSprites[spriteIndex], (0 - age * 7) | 0)
})
}
const letters = { b: 32, u: 33, y: 34, p: 35, e: 36 }
function drawAd(S) {
if (S.frame - S.lastAd < 40) {
;[...'buy pepu'].forEach((char, i, message) => {
sprite(
37 + i * 7,
64,
letters[char],
(-4 +
(7 *
Math.cos(-(S.frame - S.lastAd) / 10 + (i / message.length) * PI) *
0.5 +
0.5)) |
0
)
})
}
}
{
"iframeVersion": "0.1.280",
"lines": [
315,
0,
0,
0,
0,
0,
0,
0
]
}
{
"0": {
"notes": [
"0c17",
"1e17",
"2g17",
"3a17",
"4a#17",
"5b17"
],
"tempo": "6",
"synth": "2"
},
"1": {
"notes": [
"0b37",
"1f32",
"2c32",
"3b27",
"4f22",
"5c23",
"6b17",
"7f15",
"8c13",
"9b07",
"10f01",
"11c00"
],
"tempo": "5",
"synth": "2"
},
"2": {
"notes": [
"0b31",
"6b31",
"10b30",
"13b30",
"15b30"
],
"tempo": "4",
"synth": "1"
},
"3": {
"notes": [
"8b32"
],
"tempo": "4",
"synth": "1"
}
}
{
"0": [
" ",
" 1001 ",
" 211112 ",
" 222222 ",
" 333333 ",
" 344443 ",
" 4554 ",
" "
],
"1": [
" ",
" 00 ",
" 1111 ",
" 222222 ",
" 333333 ",
" 4444 ",
" 55 ",
" "
],
"2": [
" ",
" ",
" 1001 ",
" 2222 ",
" 3333 ",
" 4554 ",
" ",
" "
],
"3": [
" ",
" ",
" 00 ",
" 2222 ",
" 3443 ",
" 55 ",
" ",
" "
],
"4": [
" ",
" ",
" ",
" 02 ",
" 35 ",
" ",
" ",
" "
],
"5": [
" ",
" ",
" ",
" 12 ",
" 35 ",
" ",
" ",
" "
],
"6": [
" ",
" ",
" ",
" 2 ",
" ",
" ",
" ",
" "
],
"16": [
" 12",
" 123",
" 1023 ",
" 1001 ",
" 10014 ",
"12214 ",
"2224 ",
" 24 "
],
"17": [
" ",
" 0 ",
" ",
" 0 ",
"0 ",
" ",
" ",
" 0"
],
"18": [
" 0 ",
" 0 0",
" 0 0 ",
" 0 0 ",
" 0 ",
" ",
" ",
" "
],
"19": [
" 0 ",
" 0 ",
" 0 0 ",
" 0 0 ",
" 0 0 ",
" 0 ",
" ",
" "
],
"20": [
" 000 ",
" 0 0 ",
"0 0 ",
"0 0 ",
"0 0 ",
" 0 0 ",
" 000 ",
" "
],
"21": [
"0 0 ",
" ",
" ",
" ",
" ",
" ",
"0 0 ",
" "
],
"32": [
"00000 ",
"00 00 ",
"00 00 ",
"00000 ",
"00 00 ",
"00 00 ",
"00000 ",
" "
],
"33": [
"00 00 ",
"00 00 ",
"00 00 ",
"00 00 ",
"00 00 ",
"00 00 ",
" 0000 ",
" "
],
"34": [
"00 00 ",
"00 00 ",
"00 00 ",
" 0000 ",
" 00 ",
" 00 ",
" 00 ",
" "
],
"35": [
"00000 ",
"00 00 ",
"00 00 ",
"00000 ",
"00 ",
"00 ",
"00 ",
" "
],
"36": [
"000000 ",
"00 ",
"00 ",
"00000 ",
"00 ",
"00 ",
"000000 ",
" "
],
"48": [
"0 0 ",
" 0 ",
" 0 ",
"0 ",
"0 0 0 ",
" ",
" ",
" "
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment