â ī¸ Warning â ī¸ Deprecated Code! This video tutorial contains outdated code.
đĄ If you wish to update it, any AI assistant will update the code for you in seconds.
đĄ If you wish to update it, any AI assistant will update the code for you in seconds.
Enemy Squadron JavaScript CSS Game Development Demo
Learn some animation and control techniques in the DOM for creating browser-based games. The primary techniques of the example are randomized enemy flight patterns, keeping things in bounds, increasing difficulty, enemy collision for shield depletion when hit, and simple character control.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Enemy Squadron by Adam Khoury</title>
<meta name="author" content="Adam Khoury">
<style>
body{margin:0px; overflow-x:hidden; background:#000; font-family:Arial, Helvetica, sans-serif; font-size:17px;}
div#gamewindow{
height:500px;
background:#000;
border-bottom:#666 1px solid;
min-width:1000px;
max-width:2000px;
overflow:hidden;
}
div#gamewindow > #game_bg{
background: url(graphics/space_BG.jpg) repeat;
width: 3000px;
height: 500px;
position: relative;
top: 0px;
right: 0px;
animation: game_bg_roll linear 1.5s infinite;
}
@keyframes game_bg_roll { 100% { right: 50px; } }
div#gamewindow > div#rocket{
position:absolute;
background:url(graphics/rocket.png);
width:144px;
height:76px;
overflow:hidden;
top:200px;
left:0px;
}
div.enemy{
position:absolute;
background: url(graphics/enemy_red.png);
width:100px;
height:50px;
overflow:hidden;
top:200px;
right:-102px;
}
.efp1{ animation: efp_1 linear 5s 1; }
.efp2{ animation: efp_2 linear 5s 1; }
.efp3{ animation: efp_3 linear 5s 1; }
.efp4{ animation: efp_4 linear 5s 1; }
.efp5{ animation: efp_5 linear 5s 1; }
.efp6{ animation: efp_6 linear 5s 1; }
.efp7{ animation: efp_7 linear 5s 1; }
.efp8{ animation: efp_8 linear 5s 1; }
.efp9{ animation: efp_9 linear 5s 1; }
.efp10{ animation: efp_10 linear 5s 1; }
@keyframes efp_1 { 0% { right: 0%; top:50px; } 50% { right: 50%; top:50px; } 100% { right: 100%; top:50px; } }
@keyframes efp_2 { 0% { right: 0%; top:150px; } 50% { right: 50%; top:150px; } 100% { right: 100%; top:150px; } }
@keyframes efp_3 { 0% { right: 0%; top:250px; } 50% { right: 50%; top:250px; } 100% { right: 100%; top:250px; } }
@keyframes efp_4 { 0% { right: 0%; top:350px; } 50% { right: 50%; top:350px; } 100% { right: 100%; top:350px; } }
@keyframes efp_5 { 0% { right: 0%; top:450px; } 50% { right: 50%; top:450px; } 100% { right: 100%; top:450px; } }
@keyframes efp_6 { 0% { right: 0%; top:450px; } 20% { right: 20%; top:200px; } 100% { right: 100%; top:50px; } }
@keyframes efp_7 { 0% { right: 0%; top:50px; } 50% { right: 50%; top:50px; } 100% { right: 100%; top:450px; } }
@keyframes efp_8 { 0% { right: 0%; top:250px; } 25% { right: 25%; top:50px; } 50% { right: 50%; top:450px; } 75% { right: 75%; top:50px; } 100% { right: 100%; top:450px; } }
@keyframes efp_9 { 0% { right: 0%; top:300px; } 10% { right: 10%; top:50px; } 30% { right: 30%; top:450px; } 50% { right: 50%; top:200px; } 80% { right: 80%; top:450px; } 100% { right: 100%; top:50px; } }
@keyframes efp_10 { 0% { right: 0%; top:450px; } 10% { right: 10%; top:400px; } 20% { right: 20%; top:200px; } 30% { right: 30%; top:400px; } 40% { right: 40%; top:200px; } 50% { right: 50%; top:400px; } 60% { right: 60%; top:200px; } 70% { right: 70%; top:50px; } 80% { right: 80%; top:200px; } 90% { right: 90%; top:400px; } 100% { right: 100%; top:450px; } }
div#gameconsole{
position:absolute;
top:20px;
left:0px;
color:#999;
font-weight:bold;
padding-left:20px;
opacity:0.7;
display:none;
}
div#gameconsole > #stopwatch{font-family:"Courier New", Courier, monospace; color:#FFF;}
div#gameconsole > #health_meter_mc{float:left; width:300px; height:16px; border: #86A800 1px solid;}
div#gameconsole > #health_meter_mc > #healthmeter{width:300px; height:16px; background: #01f9df; color:#000; font-size:12px;}
div#newgamewindow{
position:fixed;
top:40px;
left:40px;
width:550px;
height:340px;
background:#000;
display:none;
border:#666 1px solid;
border-radius:5px;
opacity:0.6;
color:#FFF;
padding:36px;
line-height:1.7em;
}
div#newgamewindow > button{ font-size:24px; padding:12px; }
div#endgamewindow{
position:fixed;
top:40px;
left:40px;
width:550px;
height:340px;
background:#000;
display:none;
border:#666 1px solid;
border-radius:5px;
opacity:0.6;
color:#FFF;
padding:36px;
line-height:1.7em;
}
div#gameloadwindow{
position:fixed;
top:100px;
left:40px;
width:320px;
height:120px;
background:#000;
display:block;
border:#666 1px solid;
border-radius:5px;
color:#FFF;
padding:36px;
}
/* NORMAL ELEMENT STYLING */
div#bottom{
color:#CCC;
}
div#bottom > #keyinstructions{padding-right:36px;}
div#bottom > #keyinstructions > b{
padding:4px 6px;
margin-left:24px;
border:#999 1px solid;
background:#333;
border-radius:4px;
}
</style>
<script>
// Run user-agent checks here for outdated browser users and give them a message
let rocket_health = 1000;
let d_pressed = false;
let a_pressed = false;
let w_pressed = false;
let s_pressed = false;
let game_stopped = false;
document.onkeydown = function(event) {
let kc = event.keyCode;
if(kc == 68){ // D
d_pressed = true;
if(w_pressed == true){rocketNorthEast();} else if(s_pressed == true){rocketSouthEast();} else {rocketEast();}
} else if(kc == 65){ // A
a_pressed = true;
if(s_pressed == true){rocketSouthWest();} else if(w_pressed == true){rocketNorthWest();} else {rocketWest();}
} else if(kc == 87){ // W
w_pressed = true;
if(a_pressed == true){rocketNorthWest();} else if(d_pressed == true){rocketNorthEast();} else {rocketNorth();}
} else if(kc == 83){ // S
s_pressed = true;
if(a_pressed == true){rocketSouthWest();} else if(d_pressed == true){rocketSouthEast();} else {rocketSouth();}
}
}
document.onkeyup = function(event){
let kc = event.keyCode;
if(kc == 68){ // D
d_pressed = false;
if(w_pressed == true){rocketNorth();} else if(s_pressed == true){rocketSouth();} else if(a_pressed == true){rocketWest();}
} else if(kc == 65){ // A
a_pressed = false;
if(w_pressed == true){rocketNorth();} else if(s_pressed == true){rocketSouth();} else if(d_pressed == true){rocketEast();}
} else if(kc == 87){ // W
w_pressed = false;
if(a_pressed == true){rocketWest();} else if(d_pressed == true){rocketEast();} else if(s_pressed == true){rocketSouth();}
} else if(kc == 83){ // S
s_pressed = false;
if(a_pressed == true){rocketWest();} else if(d_pressed == true){rocketEast();} else if(w_pressed == true){rocketNorth();}
}
if(d_pressed == false && a_pressed == false && w_pressed == false && s_pressed == false){
rocketStop();
}
}
function rocketEast() {
rocket.style.top = rocket.offsetTop+"px";
rocket.style.transition = "left 2s linear 0s";
rocket.style.left = window.innerWidth-rocket.offsetWidth+"px";
}
function rocketWest() {
rocket.style.top = rocket.offsetTop+"px";
rocket.style.transition = "left 2s linear 0s";
rocket.style.left = "0px";
}
function rocketNorth() {
rocket.style.left = rocket.offsetLeft+"px";
rocket.style.transition = "top 1s linear 0s";
rocket.style.top = "0px";
}
function rocketSouth() {
rocket.style.left = rocket.offsetLeft+"px";
rocket.style.transition = "top 1s linear 0s";
rocket.style.top = "420px";
}
function rocketNorthEast() {
rocket.style.transition = "left 2s linear 0s, top 1s linear 0s";
rocket.style.left = window.innerWidth-rocket.offsetWidth+"px";
rocket.style.top = "0px";
}
function rocketSouthEast() {
rocket.style.transition = "left 2s linear 0s, top 1s linear 0s";
rocket.style.left = window.innerWidth-rocket.offsetWidth+"px";
rocket.style.top = "420px";
}
function rocketNorthWest() {
rocket.style.transition = "left 2s linear 0s, top 1s linear 0s";
rocket.style.left = "0px";
rocket.style.top = "0px";
}
function rocketSouthWest() {
rocket.style.transition = "left 2s linear 0s, top 1s linear 0s";
rocket.style.left = "0px";
rocket.style.top = "420px";
}
function rocketStop() {
rocket.style.top = rocket.offsetTop+"px";
rocket.style.left = rocket.offsetLeft+"px";
}
function Endgame(){
this.ender = function ender(){
game_stopped = true;
window.onblur = function() { return false; };
//gamewindow.removeChild(rocket);
gameconsole.style.display = "none";
window.squadGenerate = function() { return false; }
endgamewindow.style.display = "block";
endtimedisplay.innerHTML = "You survived for " + stopwatch.innerHTML;
}
}
function enemy(){
this.spawn = function spawn(efp){
let new_enemy = document.createElement("div");
new_enemy.id = "enemy_"+Math.floor(Math.random() * 1000000000000);
new_enemy.setAttribute("class","enemy efp"+efp+"");
gamewindow.appendChild(new_enemy);
this.hittest(new_enemy.id);
}
this.hiteffects = function hiteffects(rocket){
if( healthmeter.offsetWidth > 1 ){
rocket.style.background = "url(graphics/rocket_hit.png)";
setTimeout(function(){ rocket.style.background = "url(graphics/rocket.png)";}, 100 );
}
}
this.hittest = function hittest(eid){
if( game_stopped ){ return false; }
let me = this;
let enemy = document.getElementById(eid);
let rt = rocket.offsetTop;
let rb = rocket.offsetTop+rocket.offsetHeight;
let rl = rocket.offsetLeft;
let rr = rocket.offsetLeft+rocket.offsetWidth;
let et = enemy.offsetTop;
let eb = enemy.offsetTop+enemy.offsetHeight;
let el = enemy.offsetLeft;
let er = enemy.offsetLeft+enemy.offsetWidth;
if(rr > el && rl < er && rb > et && rt < eb){
healthmeter.style.width = healthmeter.offsetWidth - 3+"px";
if(healthmeter.offsetWidth < 1){
rocket.style.background = "url(graphics/rocket_explode.png)";
setTimeout(function(){me.ender();}, 500);
return false;
} else {
this.hiteffects(rocket);
}
}
setTimeout(function(){me.hittest(eid);}, 33);
}
}
enemy.prototype = new Endgame();
function startNewGame(){
window.onresize = resizeHandler;
window.onblur = blurHandler;
newgamewindow.style.display = "none";
gameconsole.style.display = "block";
let hero = document.createElement("div");
hero.id = "rocket";
gamewindow.appendChild(hero);
squadGenerate(0,1);
clockem(0);
}
function squadGenerate(wc,sc){
let na = "1 2 3 4 5 6 7 8 9 10".split(" ");
for(let i=0; i < sc; i++){
let rand = Math.floor(Math.random() * na.length);
let efp = na.splice(rand,1);
let en = new enemy();
en.spawn(efp);
}
wc++;
if(wc > 80){
sc = 7;
} else if(wc > 40){
sc = 6;
} else if(wc > 20){
sc = 5;
} else if(wc > 10){
sc = 4;
} else if(wc > 5){
sc = 3;
} else if(wc > 2){
sc = 2;
}
setTimeout('squadGenerate('+wc+','+sc+')',5000);
}
function clockem(secs) {
secs++;
let m = Math.floor(secs / 60);
let s = secs % 60;
if(s<10) {s="0"+s;}
if(m<10) {m="0"+m;}
stopwatch.innerHTML = m+":"+s;
let timer = setTimeout('clockem('+secs+')',1000);
}
function resizeHandler(){
alert("You cannot resize the game viewport during play. We will restart the game now.");
window.location = window.location;
}
function blurHandler(){
alert("You cannot minimize or tab away during game play. We will restart the game now.");
window.location = window.location;
}
function init(){
gameloadwindow.style.display = "none";
newgamewindow.style.display = "block";
}
window.onload = init;
</script>
</head>
<body>
<div id="gamewindow"><div id="game_bg"></div></div>
<div id="newgamewindow">
<h1>Enemy Squadron<img src="graphics/rocket.png" alt="rocket" style="float:right;"></h1>
<button onclick="startNewGame()">START NEW GAME</button>
<p>Enemy Squadron is an experimental browser based game demo that has been programmed using CSS as the animation engine, and JavaScript as the user-interaction control system. Adam did not spend much time on it, about 4 hours total programming. It is very incomplete. It was made only to showcase randomized flight patterns, enemy hit-test for shield depletion on contact, and simple character control.</p>
<p style="text-align:right; font-style:italic; font-size:14px;">CSS+JS Game Demo By Adam Khoury</p>
</div>
<div id="endgamewindow">
<h2>GAME OVER</h2>
<p id="endtimedisplay"></p>
<p id="endgamestatus"></p>
</div>
<div id="gameloadwindow">
<h2>Loading game assets...</h2>
</div>
<div id="gameconsole"><div id="health_meter_mc"><div id="healthmeter">SHIELDS</div></div> Time Elapsed: <span id="stopwatch"></span></div>
<div id="bottom">
<h1 style="display:inline; padding-right:36px;">Enemy Squadron</h1>
<span id="keyinstructions"><b>W</b> ↑ <b>S</b> ↓ <b>A</b> ← <b>D</b> →</span>
<h2>Objective: Stay alive as long as you can.</h2>
<audio controls="controls" autoplay="autoplay" loop="loop"><source src="game_audio.mp3" type="audio/mpeg"></audio>
</div>
<div style="width:10px; height:1px; overflow:hidden; position:fixed; left:-200px;"><img src="graphics/rocket.png" alt="rocket"><img src="graphics/enemy_red.png" alt="enemy_red"><img src="graphics/rocket_hit.png" alt="rocket_hit"><img src="graphics/rocket_explode.png" alt="rocket_explode"></div>
</body>
</html>