297 lines
7.0 KiB
HTML
297 lines
7.0 KiB
HTML
<html>
|
|
|
|
<head>
|
|
<style type="text/css">
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
border: 0;
|
|
background: black;
|
|
overflow: hidden;
|
|
}
|
|
|
|
div {
|
|
position: absolute;
|
|
margin: 0;
|
|
padding: 0;
|
|
border: 0;
|
|
outline: 0;
|
|
font-family: arial;
|
|
font-size: 12px;
|
|
color: white;
|
|
text-align: center;
|
|
}
|
|
|
|
#viewport {
|
|
width: 100%;
|
|
height: 100%;
|
|
overflow: hidden;
|
|
top: 0px;
|
|
left: 0px;
|
|
margin-left: 0px;
|
|
margin-top: 0px;
|
|
}
|
|
|
|
#plane {
|
|
width: 88px;
|
|
height: 73px;
|
|
background-image: url(sheet.png);
|
|
-webkit-animation: cycle_sprites 300ms steps(1) infinite;
|
|
animation: cycle_sprites 300ms steps(1) infinite;
|
|
}
|
|
|
|
@-webkit-keyframes cycle_sprites {
|
|
0% {
|
|
background-position: -330px -1371px;
|
|
}
|
|
|
|
33.33% {
|
|
background-position: -372px -1132px;
|
|
}
|
|
|
|
66.66% {
|
|
background-position: -222px -1562px;
|
|
}
|
|
}
|
|
|
|
@keyframes cycle_sprites {
|
|
0% {
|
|
background-position: -330px -1371px;
|
|
}
|
|
|
|
33.33% {
|
|
background-position: -372px -1132px;
|
|
}
|
|
|
|
66.66% {
|
|
background-position: -222px -1562px;
|
|
}
|
|
}
|
|
</style>
|
|
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, maximum-scale=1">
|
|
<script src="jquery-3.6.0.min.js"></script>
|
|
</head>
|
|
|
|
<body>
|
|
<script>
|
|
// Setup
|
|
function timestamp() {
|
|
return window.performance && window.performance.now ? window.performance.now() : new Date().getTime();
|
|
}
|
|
|
|
var now,
|
|
dt = 0,
|
|
last = timestamp(),
|
|
step = 1 / 60;
|
|
|
|
const GameState = {
|
|
PLAYING: 0,
|
|
STARTSCREEN: 1
|
|
};
|
|
|
|
var current_gamestate = GameState.STARTSCREEN;
|
|
var has_died = false;
|
|
|
|
|
|
function frame() {
|
|
now = timestamp();
|
|
dt = dt + Math.min(1, (now - last) / 1000);
|
|
|
|
while (dt > step) {
|
|
dt = dt - step;
|
|
update(step);
|
|
}
|
|
|
|
render(dt);
|
|
|
|
last = now;
|
|
requestAnimationFrame(frame);
|
|
}
|
|
|
|
// Game
|
|
const GRAVITY = 200
|
|
const JUMP_VEL = 200
|
|
const SPIKE_DISTANCE = 400
|
|
|
|
class Bird {
|
|
constructor() {
|
|
this.position_x = 100;
|
|
this.position_y = 100;
|
|
|
|
this.width = 88;
|
|
this.height = 73;
|
|
|
|
this.velocity_y = 0;
|
|
}
|
|
}
|
|
|
|
class Spikes {
|
|
constructor() {
|
|
this.position_x = 350;
|
|
this.position_y = 0;
|
|
}
|
|
}
|
|
|
|
let player = new Bird()
|
|
|
|
// Fixed time loop
|
|
function update(dt) {
|
|
if (current_gamestate == GameState.PLAYING) {
|
|
player.position_y += player.velocity_y * dt;
|
|
player.position_x += 100 * dt;
|
|
|
|
// Clamp at top
|
|
if (player.position_y < 0) {
|
|
player.position_y = 0;
|
|
player.velocity_y = 0;
|
|
}
|
|
|
|
// Gravity
|
|
player.velocity_y += GRAVITY * dt;
|
|
|
|
// Lose condition
|
|
if (player.position_y > 400) {
|
|
die();
|
|
}
|
|
} else if (current_gamestate == GameState.STARTSCREEN) {
|
|
// Do nothing
|
|
}
|
|
}
|
|
|
|
// Variable time render loop
|
|
function render(dt) {
|
|
$("#plane").css({
|
|
top: player.position_y + "px",
|
|
left: player.position_x + "px"
|
|
});
|
|
|
|
if (current_gamestate == GameState.STARTSCREEN) {
|
|
if (has_died == false) {
|
|
$("#get_ready").css({ visibility: "visible" });
|
|
$("#game_over").css({ visibility: "hidden" });
|
|
} else {
|
|
$("#get_ready").css({ visibility: "hidden" });
|
|
$("#game_over").css({ visibility: "visible" });
|
|
}
|
|
} else {
|
|
$("#get_ready").css({ visibility: "hidden" });
|
|
$("#game_over").css({ visibility: "hidden" });
|
|
}
|
|
}
|
|
|
|
|
|
function die() {
|
|
current_gamestate = GameState.STARTSCREEN;
|
|
has_died = true;
|
|
}
|
|
|
|
function restart() {
|
|
player.position_x = 100;
|
|
player.position_y = 100;
|
|
|
|
player.velocity_y = 0;
|
|
|
|
current_gamestate = GameState.PLAYING;
|
|
}
|
|
|
|
document.onmousedown = function (evt) {
|
|
if (current_gamestate == GameState.PLAYING) {
|
|
// Jump
|
|
player.velocity_y = -JUMP_VEL;
|
|
} else if (current_gamestate == GameState.STARTSCREEN) {
|
|
restart();
|
|
}
|
|
};
|
|
|
|
requestAnimationFrame(frame);
|
|
</script>
|
|
|
|
|
|
|
|
<div id="viewport">
|
|
<div id="floor" style="
|
|
left:0px;
|
|
top:409px;
|
|
background-image:url(sheet.png);
|
|
background-position: -0px -142px;
|
|
width: 800px;
|
|
height: 71px;
|
|
z-index: -1;
|
|
">
|
|
</div>
|
|
<div id="background" style="
|
|
left:0px;
|
|
top:0px;
|
|
background-image:url(sheet.png);
|
|
background-position: -0px -355px;
|
|
width: 800px;
|
|
height: 480px;
|
|
z-index: -2;
|
|
">
|
|
</div>
|
|
<div id="plane" style="
|
|
z-index: 0;
|
|
">
|
|
</div>
|
|
|
|
<div id="spike_bottom" style="
|
|
left:300px;
|
|
top:300px;
|
|
background-image:url(sheet.png);
|
|
background-position: -0px -1757px;
|
|
width: 108px;
|
|
height: 239px;
|
|
z-index: 1;
|
|
">
|
|
</div>
|
|
|
|
<div id="spike_top" style="
|
|
left:300px;
|
|
top:-100px;
|
|
background-image:url(sheet.png);
|
|
background-position: -264px -986px;
|
|
width: 108px;
|
|
height: 239px;
|
|
z-index: 1;
|
|
">
|
|
</div>
|
|
|
|
<div id="game_over" style="
|
|
left:200px;
|
|
top:200px;
|
|
background-image:url(sheet.png);
|
|
background-position: -0px -835px;
|
|
width: 412px;
|
|
height: 78px;
|
|
z-index: 1;
|
|
">
|
|
</div>
|
|
|
|
<div id="get_ready" style="
|
|
left:200px;
|
|
top:200px;
|
|
background-image:url(sheet.png);
|
|
background-position: -0px -913px;
|
|
width: 400px;
|
|
height: 73px;
|
|
z-index: 1;
|
|
">
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
// Scale viewport to fit device width
|
|
function apply_scale() {
|
|
var scale = window.innerHeight / 480.0;
|
|
$("#viewport").css({ "transform": "scale(" + scale + ")", "transform-origin": "0 0" });
|
|
}
|
|
|
|
window.onresize = apply_scale;
|
|
|
|
apply_scale();
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html> |