Skip to content

Instantly share code, notes, and snippets.

@thykka
Last active September 5, 2020 15:23
Show Gist options
  • Save thykka/53ae66e13efcee303c9f9d94b385e26e to your computer and use it in GitHub Desktop.
Save thykka/53ae66e13efcee303c9f9d94b385e26e to your computer and use it in GitHub Desktop.
SCRIPT-8
{
"0": {
"0": {
"3": "2"
},
"1": {
"3": "2"
},
"2": {
"3": "2"
},
"3": {
"3": "2"
},
"4": {
"0": "3",
"3": "2"
},
"5": {
"0": "3",
"3": "2"
},
"6": {
"0": "3",
"3": "2"
},
"7": {
"0": "3",
"3": "2"
},
"8": {
"0": "3",
"2": 2,
"3": "2"
},
"9": {
"0": "3",
"2": 2,
"3": "2"
},
"10": {
"0": "3",
"2": 2,
"3": "2"
},
"11": {
"0": "3",
"2": 2,
"3": "2"
},
"12": {
"0": "3",
"3": "2"
},
"13": {
"0": "3",
"3": "2"
},
"14": {
"0": "3",
"3": "2"
},
"15": {
"0": "3",
"3": "2"
},
"tempo": "2"
},
"1": {
"0": {
"3": "2"
},
"1": {
"3": "2"
},
"2": {
"3": "2"
},
"3": {
"3": "2"
},
"4": {
"3": "2"
},
"5": {
"3": "2"
},
"6": {
"3": "2"
},
"7": {
"3": "2"
},
"8": {
"3": "2"
},
"9": {
"3": "2"
},
"10": {
"3": "2"
},
"11": {
"3": "2"
},
"12": {
"3": "2"
},
"13": {
"3": "2"
},
"14": {
"3": "2"
},
"15": {
"3": "2"
},
"tempo": 0
}
}
// title: Flappy PePu
const BIRD = 1;
init = state => {
state.spriteFont = {
// char: [sprite, width]
A: [19, 7], C: [16, 7], D: [24, 6],
E: [18, 4], F: [25, 4], I: [21, 2],
L: [26, 4], N: [23, 6], O: [27, 5],
P: [27, 5], R: [17, 5], T: [20, 6],
U: [29, 6],
V: [22, 7], Y: [28, 6], ' ': [31, 5]
};
state.time = 0;
state.gravity = 0// 1 / 9.8;
state.walls = [];
state.wallsSpawned = 0;
state.wallSpeed = 1;
state.hiScore = state.hiScore | 0;
state.score = 0;
state.held = {
a: false
};
state.actors = [
{ // bird
id: 1,
x: 24, y: 8,
vx: 0, vy: 0,
// sprite: 32,
sprites: [[32, 33], [34, 35], [36, 37], [38, 39]]
}
];
state.bgWalls = Array.from({ length: 5 }, () => createWall(state, false, true));
}
function createWall(state, foreground = false, init = false) {
const gapStartY = Math.random() * 96 | 0;
const minGapHeight = (64 - state.wallsSpawned)
const maxGapHeight = 128 - gapStartY;
const gapHeight = minGapHeight + Math.random() * (maxGapHeight - minGapHeight) | 0;
const x = init ? Math.random() * 128 | 0 : 128,
y1 = 0,
w = foreground ? 8 : (Math.random() * 4 + 4);
const h1 = gapStartY;
const y2 = gapStartY + gapHeight;
const h2 = 128 - y2;
return {
x, y1, y2, w, h1, h2
};
}
update = (state, input, elapsed) => {
state.elapsed = elapsed / (1000 / 60);
state.time += elapsed;
const bird = state.actors.find(a => a.id === 1);
updateWalls(bird, state);
updateBgWalls(state);
updateBird(bird, state, input);
if(bird.dead && input.b) {
init(state);
}
}
function updateBgWalls(state) {
state.bgWalls = state.bgWalls.filter(w => w.x + w.w >= 0);
while(state.bgWalls.length < 10) {
state.bgWalls.push(createWall(state))
}
state.bgWalls.forEach(wall => {
wall.x -= state.wallSpeed * state.elapsed * (wall.w - 1) / 8;
});
}
function updateWalls(bird, state) {
if(state.gravity > 0 && !bird.dead && state.walls.length === 0) {
const wall = createWall(state, true);
wall.id = ++state.wallsSpawned
state.walls.push(wall);
state.score += (state.wallsSpawned - 1) * 2
state.wallSpeed = Math.min(state.wallSpeed * 1.05, 3);
}
state.walls.forEach(wall => {
wall.x -= state.wallSpeed * state.elapsed;
});
state.walls = state.walls.filter(w => w.x + w.w >= 0);
}
function updateBird(bird, state, input) {
if(state.gravity === 0 && input.a) {
// begin game
state.gravity = 1 / 9.8;
state.held.a = true;
playSong(0)
}
// game over
if(state.gravity === 0 || bird.dead) return;
// hit check
const wallHit = state.walls.reduce((hit, wall) => {
return (
bird.x + 8 > wall.x && bird.x < wall.x + wall.w &&
(bird.y < wall.h1 || bird.y + 8 > wall.y2)
);
}, false);
// death
if(wallHit || bird.y > 127 || bird.y < -7) {
bird.dead = true;
bird.vy = 0;
state.wallSpeed = 0;
state.hiScore = Math.max(state.score, state.hiScore);
stopSong();
playPhrase(1);
return;
}
// jump
if(input.a && !state.held.a) {
bird.vy = -2;
//bird.sprite = bird.sprites[1];
state.held.a = true;
playPhrase(0)
} else {
bird.vy = Math.min(bird.vy + state.gravity, 4);
}
// after jump
if(!input.a && state.held.a) {
//bird.sprite = bird.sprites[0];
state.held.a = false;
}
// move bird
bird.x = bird.x + bird.vx * state.elapsed;
bird.y = bird.y + bird.vy * state.elapsed;
state.score += 1 / 64
}
draw = state => {
clear(6);
drawBgWalls(state);
drawBird(state);
drawWalls(state);
rectFill(0, 0, 128, 16, 7);
drawIntro(state);
}
function drawBird(state) {
const bird = state.actors[0]
const sprites = bird.sprites[clamp(Math.round(bird.vy * -3), 0, bird.sprites.length - 1)]
sprite(bird.x, bird.y, sprites[0])
sprite(bird.x, bird.y - 8, sprites[1])
}
function drawBgWalls(state) {
state.bgWalls.forEach(wall => {
rectFill(wall.x, wall.h1, wall.w, wall.y2 + wall.h2, 7)
})
}
function drawIntro(state) {
const bird = state.actors.find(a => a.id === 1);
const t = (state.time / 1000);
if(t <= 1) {
drawCNLogo(1, 0, state);
}
if(t > 1) {
drawScore(state, bird);
drawCNLogo(1, 0, state);
drawInstructions(64, 0, state);
}
}
function drawInstructions(x, y, state) {
if(state.gravity === 0) {
const color = state.time % 16 > 8 ? 6 : 2;
print(x, y, 'Press A', color)
} else {
print(x, y, 'Best: ' + Math.floor(state.hiScore), 2);
}
}
function drawScore(state, bird) {
const score = Math.floor(state.score);
if(bird.dead) {
rectFill(0, 49, 128, 7, 7)
print(46, 50, 'Game over!', 0)
const scoreWidth = score.toString().length * 2;
rectFill(0, 95, 128, 7, 7)
print(31, 96, 'press b to restart', 3)
if(state.score === state.hiScore) {
rectFill(0, 64, 128, 14, 7)
print(27, 72, '>> New hi-score!!! <<', 0)
} else {
rectFill(0, 64, 128, 7, 7)
}
print(40 - scoreWidth, 65, 'final score: ' + score, 3)
} else {
print(64, 9, 'score: ' + score, 6)
}
}
function drawWalls(state, wallColor = 4) {
state.walls.forEach(wall => {
const {
x, w, h1, h2, y1, y2
} = wall;
rectFill(
x, y1,
w, h1,
wallColor
);
rectFill(
x, y2,
w, h2,
wallColor
);
})
}
function drawCNLogo(x, y, state) {
const font = state.spriteFont;
const { time } = state;
const fadeStart = 0;
const fadeDuration = 500;
const transStart = 100;
const transDuration = 1000;
const flappyX = x;
const fadeInTime = Math.min(1, time / fadeDuration);
const fadeShade = (-7 + fadeInTime * 7) | 0;
const relTime = (time - transStart) / transDuration;
const easeTime = 1 - (1 - relTime) * (1 - relTime);
const creativeX = 0 + (relTime < 0 ? x : x + easeTime * 96);
if(relTime < 0) {
} else if(relTime > 0 && relTime < 1) {
printSprite(flappyX + 96 - easeTime * 96, y, 'FLAPPY', font, (-7 + relTime * 7) | 0);
printSprite(x + 112 - easeTime * 112, y + 8, 'PEPU', font, fadeShade);
} else {
printSprite(flappyX, y, 'FLAPPY', font);
printSprite(x, y + 8, 'PEPU', font, fadeShade);
}
}
function printSprite(x, y, message, font, shade = 0) {
let xpos = x;
[...message].forEach((char, index) => {
try {
const [spriteIndex, width] = font[char];
sprite(xpos, y, spriteIndex, shade);
xpos += width + 1;
} catch(e) {
log('Missing sprite: ' + char)
}
});
}
function drawCraslogo(x, y, shade = 6) {
[0, 1, 2, 3, 4].forEach((sp, i) => {
sprite(x + i*8, y, sp, 0 - shade);
});
print(x+2, y+8, 'presents:', shade)
}
{
"iframeVersion": "0.1.280",
"lines": [
277,
0,
0,
0,
0,
0,
0,
0
]
}
{
"0": {
"notes": [
"0c17",
"1e13",
"2g#12",
"3c21",
"4e20",
"5g#20"
],
"tempo": "4",
"synth": "2"
},
"1": {
"notes": [
"0c27",
"2a17",
"4g17",
"6f#17",
"9f17",
"13e17"
],
"tempo": "4",
"synth": "1"
},
"2": {
"notes": [
"0c17",
"2c12",
"4c17",
"6c12",
"8c17",
"9c12",
"11c17",
"13c12",
"15c17"
],
"tempo": "2",
"synth": "3"
},
"3": {
"notes": [
"2g02",
"6g02",
"10g02",
"14g02",
"15a#02"
],
"tempo": "2",
"synth": "0"
}
}
{
"0": {
"0": 0,
"1": 0,
"2": 0,
"3": 0,
"4": 0,
"5": 0,
"6": 0,
"7": 0,
"8": 0,
"9": 0,
"10": 0,
"11": 0,
"12": 0,
"13": 0,
"14": 0,
"15": 0,
"tempo": "2"
}
}
{
"16": [
" 000 ",
" 00000 ",
"00 00 ",
"00 ",
"00 00 ",
" 00000 ",
" 000 ",
" "
],
"17": [
"0000 ",
"00000 ",
"00 00 ",
"00000 ",
"0000 ",
"00000 ",
"00 00 ",
" "
],
"18": [
"0000 ",
"0000 ",
" ",
"0000 ",
" ",
"0000 ",
"0000 ",
" "
],
"19": [
" 0 ",
" 000 ",
" 000 ",
" 00 00 ",
" 00 00 ",
"0000000 ",
"00 00 ",
" "
],
"20": [
"000000 ",
"000000 ",
" 00 ",
" 00 ",
" 00 ",
" 00 ",
" 00 ",
" "
],
"21": [
"00 ",
"00 ",
"00 ",
"00 ",
"00 ",
"00 ",
"00 ",
" "
],
"22": [
"00 00 ",
"00 00 ",
" 00 00 ",
" 00 00 ",
" 000 ",
" 000 ",
" 0 ",
" "
],
"23": [
"0 00 ",
"00 00 ",
"000 00 ",
"000000 ",
"00 000 ",
"00 00 ",
"00 0 ",
" "
],
"24": [
"0000 ",
"00000 ",
"00 00 ",
"00 00 ",
"00 00 ",
"00000 ",
"0000 ",
" "
],
"25": [
"0000 ",
"0000 ",
"00 ",
"0000 ",
"0000 ",
"00 ",
"00 ",
" "
],
"26": [
"00 ",
"00 ",
"00 ",
"00 ",
"00 ",
"0000 ",
"0000 ",
" "
],
"27": [
"0000 ",
"00000 ",
"00 00 ",
"00000 ",
"0000 ",
"00 ",
"00 ",
" "
],
"28": [
"00 00 ",
"00 00 ",
"000000 ",
" 0000 ",
" 00 ",
" 00 ",
" 00 ",
" "
],
"29": [
"00 00 ",
"00 00 ",
"00 00 ",
"00 00 ",
"00 00 ",
"000000 ",
" 0000 ",
" "
],
"32": [
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 0",
"00000000"
],
"33": [
" 0000 ",
" 0 0 ",
" 0 0 ",
" 0 0 ",
" 0 0 ",
"0 0",
"0 0",
"0 0"
],
"34": [
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 111 0",
"0 0",
"00000000"
],
"35": [
" 0000 ",
" 0 0 ",
" 0 0 ",
" 0 0 ",
" 0 0 ",
"0 1 0",
"0 1 0",
"0 111 0"
],
"36": [
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 1 1 0",
"0 1 1 0",
"0 0",
"00000000"
],
"37": [
" 0000 ",
" 0 0 ",
" 0 0 ",
" 0 0 ",
" 0 0 ",
"0 11 0",
"0 1111 0",
"0 1111 0"
],
"38": [
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 1111 0",
"0 1 0",
"0 0",
"0 0",
"00000000"
],
"39": [
" 0000 ",
" 0 0 ",
" 0 0 ",
" 0 0 ",
" 0 0 ",
"0 11 0",
"0 1111 0",
"0 1111 0"
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment