<div id='game_console'>
<div id='player'><div id='level_mask'></div></div>
<div id='big_rocket'></div>
<div id='game_alert'></div>
</div>
:root {
--tile-line-height: 30px;
--tile-size: 10px;
--clr: gray;
--pl-clr:
radial-gradient(circle at 75% 50%, white 1px, transparent 2px),
radial-gradient(circle at 25% 50%, white 1px, transparent 2px),
radial-gradient(circle at 75% 40%, black 3px, transparent 4px),
radial-gradient(circle at 25% 40%, black 3px, transparent 4px),
white;
}
html,
body {
min-width: 100vw;
min-height: 100vh;
overflow: hidden;
margin: 0;
display: grid;
place-items: center;
background: #111;
}
#game_console {
width: 100%;
max-width: 1000px;
aspect-ratio: 16 / 9;
position: relative;
background: #200;
text-align: center;
line-height: var(--tile-line-height);
font-size: 0;
color: transparent;
user-select: none;
box-shadow: 0 20px 20px black;
}
#game_alert {
padding: 1rem 2rem;
font-size: 16px;
font-family: system-ui, serif;
color: white;
background: rgba(0,0,0,.75);
/* box-sizing: border-box; */
border: 1px dashed white;
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
z-index: 99999;
border-radius: 50px;
transition: .5s;
opacity: 0;
pointer-events: none;
user-select: none;
}
h2 {
margin: 0;
margin-bottom: 10px;
}
.tile {
/* outline: 1px dotted dimgray; */
}
.ground {
background: dimgray;
box-shadow:
inset 2px 2px 0 2px rgba(0,0,0,.25),
inset -2px -2px 0 2px rgba(0,0,0,.5);
}
.door {
box-shadow: none !important;
}
.cube {
background: var(--clr);
box-sizing: border-box;
border-top: 5px solid rgba(0,0,0,.25);
border-right: 5px solid rgba(0,0,0,.65);
border-bottom: 5px solid rgba(0,0,0,.65);
border-left: 5px solid rgba(0,0,0,.25);
}
.stripes {
background:
linear-gradient(to right, transparent 3px, rgba(0,0,0,.25) 2px),
var(--clr);
background-size: 6px 11px;
background-repeat: repeat-x;
background-position: 3px 5px;
}
.lava {
background:
linear-gradient(to top, orangered, gold 90%, transparent 90%);
background-size: 100% 200%;
background-position: 0 0;
}
.key,
.finalgoal {
box-sizing: border-box;
border-top: 5px solid rgba(0,0,0,.25);
border-right: 5px solid rgba(0,0,0,.65);
border-bottom: 5px solid rgba(0,0,0,.65);
border-left: 5px solid rgba(0,0,0,.25);
}
.highjump {
clip-path: polygon(40% 100%, 60% 100%, 100% 0%, 0% 0%);
background: linear-gradient(to bottom, aqua 3px, transparent 3px);
background-size: 100% 6px;
}
#player,
#player:after {
content:'';
width: var(--tile-line-height);
height: var(--tile-line-height);
background: transparent;
position: absolute;
/* left: calc(var(--tile-line-height)*27);
top: calc(var(--tile-line-height)*13); */
z-index: 10000;
pointer-events: none;
}
#player:after {
background: var(--pl-clr);
position: absolute;
top: 0;
left: 0;
z-index: 10000;
border-radius: 5px;
clip-path: polygon(0% 0%, 100% 0%, 100% 80%, 90% 80%, 90% 100%, 80% 100%, 80% 80%, 20% 80%, 20% 100%, 10% 100%, 10% 80%, 0% 80%);
pointer-events: none;
transform-origin: 50% 100%;
}
.goleft:after {
transform: skewX(10deg);
animation: moving .25s linear infinite;
}
.goright:after {
transform: skewX(-10deg);
animation: moving .25s linear infinite;
}
@keyframes moving {
50% {
clip-path: polygon(0% 0%, 100% 0%, 100% 80%, 80% 80%, 80% 100%, 70% 100%, 70% 80%, 30% 80%, 30% 100%, 20% 100%, 20% 80%, 0% 80%)
}
}
#level_mask {
width: 200vw;
height: 200vw;
background: radial-gradient(circle at 50% 50%, rgba(255,255,255,0), black 12.5%);
position: absolute;
left: 0;
top: 0;
transform: translate(-50%,-50%);
opacity: 1;
}
.rocket {
/* opacity: 0; */
}
#big_rocket {
width: 40px;
height: 125px;
background:
linear-gradient(to right, transparent 45%, firebrick 45%, firebrick 55%, transparent 55%),
radial-gradient(circle at 50% 40%, rgba(255,255,255,1) 10%, #aaa 11%, #aaa 15%, transparent 16%),
linear-gradient(to right, transparent 50%, rgba(0,0,0,.1) 50%),
linear-gradient(to bottom, firebrick 12%, transparent 12%),
lightgray;
background-size: 100% 40%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%;
background-position: 50% 95%, 0 0, 0 0, 0 0, 0 0;
background-repeat: no-repeat;
border-radius: 50px 50px 50px 50px / 200px 200px 10px 10px;
position: absolute;
left: 54.25%;
top: 0;
box-shadow: 0 15px 0 -5px gray;
}
#big_rocket:before {
content:'';
width: 200%;
height: 50%;
position: absolute;
top: 55%;
left: -50%;
background:
radial-gradient(circle at 50% 100%, transparent 50%, firebrick 51%);
clip-path: polygon(0% 0%, 25% 0%, 25% 100%, 75% 100%, 75% 0%, 100% 0%, 100% 100%, 0% 100%);
border-radius: 100% 100% 0 0;
}
#big_rocket:after {
content:'';
width: 60%;
height: 25%;
position: absolute;
top: 108%;
left: 20%;
background:
linear-gradient(to bottom, orangered, gold);
border-radius: 0 0 25% 25%;
filter: blur(2px);
opacity: .75;
animation: blast_off .75s linear infinite;
}
@keyframes blast_off {
33% {
background:
linear-gradient(to bottom, orangered 25%, gold 75%);
}
66% {
background:
linear-gradient(to bottom, orangered 50%, gold 90%);
}
}
.adios {
animation: adios 2s ease-in forwards;
}
@keyframes adios {
100% {
transform: translateY(-200%);
opacity: 0;
}
}
const gc = document.querySelector('#game_console')
const ga = document.querySelector('#game_alert')
const gc_loc = gc.getBoundingClientRect()
const pl = document.querySelector('#player')
var cols = 48 // multiple of 16
var rows = 27 // multiple of 9
const tile_size = gc_loc.width*(100/cols/100)
document.body.style.setProperty('--tile-line-height', tile_size+'px')
pl.style.top = (tile_size*13) + 'px'
pl.style.left = (tile_size*27) + 'px'
var pl_loc = pl.getBoundingClientRect()
gc.style.width = '1000px'
gc.style.height = tile_size*rows+'px'
var gravity = 8,
kd,
x = pl_loc.left,
x_speed = 5,
pb_y = 0,
score = 0,
rot = 0,
data_p = 0,
bonus = 1,
dead = false,
kd_list = [],
d = {},
highjump = false,
timer = 0;
const level = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,8,8,0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,0,
0,1,'B',1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,8,8,8,1,9,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0,
0,1,0,1,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,1,1,1,0,8,8,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,0,0,1,1,0,
0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,8,8,0,0,0,1,1,1,1,1,1,1,1,0,0,1,1,0,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,8,8,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,8,8,0,0,0,1,1,1,1,1,1,1,1,0,1,1,0,0,1,1,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,8,8,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,0,
0,1,1,1,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,2,2,0,1,1,1,0,8,8,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,0,1,1,1,0,
0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,1,1,0,
0,'BD','BD',0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,1,0,1,1,1,0,
0,1,1,1,0,1,'G',1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,
0,0,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,2,2,0,1,1,1,1,1,1,0,'PD','PD',0,0,
0,1,1,1,0,0,0,0,0,2,2,0,2,2,0,2,2,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,
0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,'GD',1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,'GD',1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,'BD',0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1,0,
0,0,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,
0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,'P',1,0,1,1,0,1,1,1,1,'H',1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,0,1,1,1,1,1,1,1,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,1,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,0,1,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,
0,0,0,1,0,1,1,0,2,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,2,0,0,2,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,2,2,0,2,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
function buildGame(){
for(var i=0;i<cols*rows;i++) {
var d = document.createElement('div')
d.className = 'tile'
if(level[i] == 0) {
// d.className = Math.random() > .2 ? 'tile ground cube' : 'tile ground stripes'
d.className = 'tile ground'
// d.style.background = 'dimgray'
}
if(level[i] == 2) {
d.className = 'tile lava'
}
if(level[i] == 8) {
// d.className = Math.random() > .2 ? 'tile rocket cube' : 'tile rocket stripes'
d.className = 'tile rocket'
d.style.background = 'dimgray'
}
if(level[i] == 9) {
d.className = 'tile finalgoal'
d.style.background = 'goldenrod'
d.style.borderRadius = '50%'
}
if(level[i] == 'B') {
d.className = 'tile key blue'
d.style.background = 'dodgerblue'
d.style.borderRadius = '50%'
}
if(level[i] == 'BD') {
d.className = 'tile door ground blue'
d.style.background = 'linear-gradient(to bottom, transparent 20%, dodgerblue 20%, dodgerblue 40%, transparent 40%, transparent 60%, dodgerblue 60%, dodgerblue 80%, transparent 80%'
}
if(level[i] == 'G') {
d.className = 'tile key green'
d.style.background = 'limegreen'
d.style.borderRadius = '50%'
}
if(level[i] == 'GD') {
d.className = 'tile door ground green'
d.style.background = 'linear-gradient(to right, transparent 20%, limegreen 20%, limegreen 40%, transparent 40%, transparent 60%, limegreen 60%, limegreen 80%, transparent 80%'
}
if(level[i] == 'P') {
d.className = 'tile key purple'
d.style.background = 'MediumOrchid'
d.style.borderRadius = '50%'
}
if(level[i] == 'PD') {
d.className = 'tile door ground purple'
d.style.background = 'linear-gradient(to bottom, transparent 20%, MediumOrchid 20%, MediumOrchid 40%, transparent 40%, transparent 60%, MediumOrchid 60%, MediumOrchid 80%, transparent 80%'
}
if(level[i] == 'H') {
d.className = 'tile highjump'
// d.style.background = 'goldenrod'
}
d.setAttribute('grid_loc', [i % cols,Math.floor(i/cols)])
d.style.width = tile_size + 'px'
d.style.height = tile_size + 'px'
d.style.position = 'absolute'
// d.innerHTML = i
// d.style.outline = '1px dotted gray'
d.style.left = (i % cols)*tile_size + 'px'
d.style.top = Math.floor(i/cols)*tile_size + 'px'
gc.appendChild(d)
}
}
buildGame()
function updatePlayer() {
var pl_loc = pl.getBoundingClientRect()
var pl_center = document.elementFromPoint(pl_loc.x + (tile_size*.5), pl_loc.y + (tile_size*.5))
var pl_xy1 = document.elementFromPoint(pl_loc.x + (pl_loc.width*.25), pl_loc.y + pl_loc.height + (gravity*.5))
var pl_xy2 = document.elementFromPoint(pl_loc.x + (pl_loc.width*.75), pl_loc.y + pl_loc.height + (gravity*.5))
var pl_xy3 = document.elementFromPoint(pl_loc.x - (x_speed*.5), pl_loc.y + (pl_loc.height*.5))
var pl_xy4 = document.elementFromPoint(pl_loc.x + pl_loc.width + (x_speed*.5), pl_loc.y + (pl_loc.height*.5))
var pl_xy5 = document.elementFromPoint(pl_loc.x + (pl_loc.width*.5), pl_loc.y - (gravity*.5))
// var pl_xy6 = document.elementFromPoint(pl_loc.x + (pl_loc.width*.5), pl_loc.y + pl_loc.height)
// console.log(pl_center)
function endGame() {
alert('you died')
}
//if dead stop, else update player and everything else
if(!pl_xy1 || !pl_xy2 || dead) {
endGame()
} else {
// set player top
// if player on ground set new top
if((pl_xy1.classList.contains('ground') ||
pl_xy2.classList.contains('ground'))) {
gravity = 0
} else {
if(gravity < 8) {
gravity += .51
} else {
gravity = 8
}
}
pl.style.top = pl_loc.top - gc_loc.top + gravity + 'px'
// console.log(gravity)
// add jump-force
if(d[38] && gravity == 0) {
gravity = -8
if(highjump) {
gravity = -9
}
}
if(pl_xy5.classList.contains('ground')) {
gravity = 5
}
pl.style.top = pl_loc.top - gc_loc.top + gravity + 'px'
// track left/right movement
if(d[37] && x > gc_loc.x) {
if(!pl_xy3.classList.contains('ground')) {
x -= x_speed
pl.className = ''
pl.classList.add('goleft')
} else {
pl.className = ''
}
}
if(d[39] && x + pl_loc.width < gc_loc.x + gc_loc.width) {
if(!pl_xy4.classList.contains('ground')) {
x += x_speed
pl.className = ''
pl.classList.add('goright')
} else {
pl.className = ''
}
}
pl.style.left = x - gc_loc.left + 'px'
if(pl_center.classList.contains('lava')) {
// console.log('lava')
pl.style.top = (tile_size*13) + 'px'
pl.style.left = (tile_size*27) + 'px'
pl_loc = pl.getBoundingClientRect()
x = pl_loc.left
}
if(pl_center.classList.contains('highjump')) {
// console.log('lava')
highjump = true
pl_center.style.display = 'none'
ga.innerHTML = 'You got high jump!'
ga.style.opacity = '1'
setTimeout(function(){
ga.style.opacity = '0'
},4000)
}
if(pl_center.classList.contains('key')) {
pl_center.style.display = 'none'
var clr = pl_center.classList[2]
ga.innerHTML = 'You got the '+clr+' key!'
ga.style.opacity = '1'
setTimeout(function(){
ga.style.opacity = '0'
},4000)
var doors = document.querySelectorAll('.door')
doors.forEach(function(elm){
if(elm.classList[3] == clr) {
elm.classList.remove('ground')
}
})
}
if(pl_center.classList.contains('door')) {
pl_center.style.display = 'none'
}
if(pl_center.classList.contains('finalgoal')) {
pl_center.style.display = 'none'
var clr = pl_center.style.background
var doors = document.querySelectorAll('.rocket')
doors.forEach(function(elm){
elm.style.display = 'none'
})
setTimeout(function(){
pl.style.opacity = '0'
document.body.style.setProperty('--pl-clr', 'transparent')
document.querySelector('#big_rocket').classList.add('adios')
setTimeout(function(){
var time = (timer/30)
ga.innerHTML = '<h2>YOU WIN!</h2>'+time.toFixed(2)+' seconds'
ga.style.opacity = '1'
// setTimeout(function(){
// ga.style.opacity = '0'
// },4000)
}, 2250)
}, 250)
}
timer++
setTimeout(updatePlayer, 1000/30)
}
}
updatePlayer()
window.focus()
ga.innerHTML = 'Arrow keys to move and jump'
ga.style.opacity = '1'
setTimeout(function(){
ga.style.opacity = '0'
},4000)
window.addEventListener('keydown', function(e) { d[e.which] = true; })
window.addEventListener('keyup', function(e) {
d[e.which] = false;
pl.className = ''
})
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.