Skip to content

Commit 8b8bfe1

Browse files
committed
Dodge the Asteroids
1 parent 4205ca4 commit 8b8bfe1

File tree

3 files changed

+218
-88
lines changed

3 files changed

+218
-88
lines changed

index.html

+13-6
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@
99
<link href="./style/style.css" rel="stylesheet">
1010
</head>
1111
<body>
12-
<h1>The Number Guessing Game!</h1>
13-
<div id="#gamecontainer">
12+
<header id="instructions">
13+
<h1>Asteroid Navigator</h1>
14+
<p>A to Move Left ; D to Move Right</p>
15+
<p>Press Spacebar to begin</p>
16+
</header>
1417

15-
<div class="mb-3">
16-
<label for="gameInput" class="form-label">Guess My Number</label>
17-
<input class="form-control" id="#gameInput" placeholder="??">
18+
<footer id="gameover">
19+
<h1>Game Over!</h1>
20+
<p>Press Spacebar to restart</p>
21+
</footer>
22+
<div id="#gamecontainer">
23+
<div class="starfield"></div>
24+
<div class="spaceship">
25+
<img src="./images/DurrrSpaceShip.png"></img>
1826
</div>
19-
<button type="button" id="#gameBtn" class="btn btn-primary" >Check My Guess</button>
2027

2128
<div id="#output"></div>
2229
</div>

scripts/script.js

+159-82
Original file line numberDiff line numberDiff line change
@@ -3,101 +3,154 @@
33
console.log("Hello World!");
44

55
/* Events */
6-
var Events = {
6+
const Events = {
77
START: 0,
8-
GUESS: 1,
9-
CORRECT: 2,
10-
INCORRECT: 3
8+
TICK: 4
119
}
1210

1311
/* States */
14-
var States = {
12+
const States = {
1513
START: 0,
1614
PLAYING: 1,
1715
GAMEOVER: 2
1816
}
1917

18+
/* Avatar direction */
19+
const Dir = {
20+
STOP: 0,
21+
LEFT: 1,
22+
RIGHT: 2
23+
}
24+
2025
/* Model */
2126
class Model {
2227
constructor () {
23-
this.gameState = States.START;
24-
this.theNumber = -1;
25-
this.guesses = 0;
26-
this.lastGuess = -1;
28+
this.init();
29+
this.setKey = this.setKey.bind(this);
30+
this.checkCollision = this.checkCollision.bind(this);
2731
}
2832

2933
init () {
30-
this.theNumber = Math.floor(Math.random() * 100) + 1
31-
this.guesses = 0
32-
this.lastGuess = -1
34+
this.gameState = States.START;
35+
this.gameTime = 0;
36+
this.avatar = {
37+
direction: Dir.STOP,
38+
position: 50,
39+
life: 20
40+
}
41+
this.direction = Dir.STOP;
42+
43+
this.asteroids = [
44+
{ x: 10, y: 110 },
45+
{ x: 30, y: 110 },
46+
{ x: 50, y: 110 },
47+
{ x: 70, y: 110 },
48+
{ x: 30, y: 110 },
49+
{ x: 50, y: 110 },
50+
{ x: 70, y: 110 },
51+
{ x: 90, y: 110 }
52+
]
53+
54+
this.keys = {
55+
'KeyA': false,
56+
'KeyD': false
57+
};
58+
59+
this.collision = false;
3360
}
3461

35-
guess (new_guess) {
36-
this.guesses++;
37-
this.lastGuess = new_guess;
38-
39-
if (new_guess == this.theNumber) {
40-
return Events.CORRECT;
62+
setKey(keyCode, isKeyDown) {
63+
this.keys[keyCode] = isKeyDown;
64+
65+
if (this.keys['KeyA']) {
66+
this.avatar.direction = Dir.LEFT;
67+
} else if (this.keys['KeyD']) {
68+
this.avatar.direction = Dir.RIGHT;
4169
} else {
42-
return Events.INCORRECT;
70+
this.avatar.direction = Dir.STOP;
4371
}
4472
}
45-
}
46-
47-
48-
/* View Interface */
49-
class View {
50-
constructor (root) {
51-
console.log("here!");
52-
this.root = root;
53-
this.gameOut = document.getElementById('#output')
54-
this.gameIn = document.getElementById("#gameInput")
55-
this.gameBtn = document.getElementById("#gameBtn")
56-
this.btn_cb = null;
57-
this.last_guess_count = 0;
5873

59-
this.btnHandler = this.btnHandler.bind(this);
60-
this.update = this.update.bind(this);
74+
updatePosition() {
75+
this.gameTime++;
76+
switch (this.avatar.direction) {
77+
case Dir.RIGHT:
78+
this.avatar.position += 1;
79+
break;
80+
case Dir.LEFT:
81+
this.avatar.position -= 1;
82+
break;
83+
}
6184

62-
console.log(this.gameBtn);
63-
this.gameBtn.addEventListener("click", this.btnHandler);
85+
this.avatar.position = Math.max(0, this.avatar.position);
86+
this.avatar.position = Math.min(95, this.avatar.position);
6487
}
6588

66-
addButtonListener( btn_cb ) {
67-
this.btn_cb = btn_cb;
89+
updateAsteroids() {
90+
this.asteroids.forEach( (pos) => {
91+
pos.y += 2;
92+
if (pos.y > 100) {
93+
pos.y = Math.random() * -100;
94+
pos.x = Math.random() * 100;
95+
}
96+
})
6897
}
6998

70-
btnHandler () {
71-
var inputText = this.gameIn.value;
72-
if (this.btn_cb) {
73-
this.btn_cb(parseInt(inputText));
74-
}
99+
checkCollision() {
100+
this.collision = false;
101+
this.asteroids.forEach( (pos, idx) => {
102+
if ((pos.y > 70) && (pos.y < 85)) {
103+
if ( ((pos.x + 15) > (this.avatar.position) ) &&
104+
((pos.x + 10) < (this.avatar.position+10)) ) {
105+
//console.log("Pos:" + pos.x + " ava:" + this.avatar.position);
106+
this.collision = true;
107+
this.avatar.life--;
108+
}
109+
}
110+
})
75111
}
112+
}
76113

77-
update (model, event) {
78-
if (model.guesses == this.last_guess_count) {
79-
return;
80-
}
81-
this.last_guess_count = model.guesses;
82-
83-
if (model.lastGuess == "") {
84-
this.gameOut.innerHTML += "Type a number between 1 and 100!<br>";
85-
}
86-
87-
if (isNaN(model.lastGuess)) {
88-
this.gameOut.innerHTML += "That wasn't a number...<br>";
89-
}
90-
91-
if (model.lastGuess == model.theNumber) {
92-
this.gameOut.innerHTML += "You got it in " + model.guesses + " tries!<br>";
93-
}
94114

95-
if (model.lastGuess < model.theNumber) {
96-
this.gameOut.innerHTML += model.lastGuess + " was too low...<br>"
97-
}
115+
/* View Interface */
116+
class View {
117+
constructor (root, model) {
118+
this.root = root;
119+
this.spaceship = document.getElementsByClassName("spaceship")[0];
120+
this.update = this.update.bind(this);
121+
this.starfield = document.getElementsByClassName("starfield")[0];
122+
model.asteroids.map( (pos, idx) => {
123+
let asteroid = document.createElement("div");
124+
asteroid.classList.add("asteroid");
125+
asteroid.innerHTML='<img src="./images/asteroid.png"></img>'
126+
asteroid.style.left = pos.x + "vw";
127+
asteroid.style.top = pos.y + "vh";
128+
asteroid.id = "asteroid" + idx;
129+
this.starfield.appendChild(asteroid);
130+
})
131+
132+
this.instructions = document.getElementById("instructions");
133+
this.gameover = document.getElementById("gameover");
134+
}
98135

99-
if (model.lastGuess > model.theNumber) {
100-
this.gameOut.innerHTML += model.lastGuess + " was too high...<br>"
136+
update (model, event) {
137+
this.instructions.style.visibility = (model.gameState == States.START) ? "" : "hidden";
138+
this.gameover.style.visibility = (model.gameState == States.GAMEOVER) ? "" : "hidden";
139+
140+
view.spaceship.style.left = model.avatar.position + "vw";
141+
model.asteroids.forEach( (pos, idx) => {
142+
let asteroid = document.getElementById("asteroid"+idx);
143+
asteroid.style.left = pos.x + "vw";
144+
asteroid.style.top = pos.y + "vh";
145+
})
146+
147+
if ((model.collision) && (model.gameState == States.PLAYING)) {
148+
this.starfield.style.background = (model.gameTime % 2) ? "red" : "white";
149+
} else {
150+
this.starfield.style.background = "black";
151+
this.starfield.style.backgroundImage = "url('./images/space5.png')";
152+
this.starfield.style.backgroundRepeat = "repeat";
153+
this.starfield.style.backgroundPosition = "0px " + model.gameTime*3 + "px";
101154
}
102155
}
103156
}
@@ -107,7 +160,6 @@ class View {
107160
class Control {
108161
constructor () {
109162
this.fsm = this.fsm.bind(this);
110-
this.guessHandler = this.guessHandler.bind(this);
111163
this.setView = this.setView.bind(this);
112164
}
113165

@@ -128,28 +180,27 @@ class Control {
128180

129181
case States.PLAYING:
130182
switch (event) {
131-
case Events.GUESS: {
132-
var result = model.guess(data);
133-
this.fsm(model, result, data);
134-
} break;
135-
case Events.CORRECT:
136-
model.gameState = States.GAMEOVER;
137-
break;
138-
case Events.INCORRECT:
139-
model.gameState = States.PLAYING;
183+
case Events.TICK:
184+
model.updatePosition();
185+
model.updateAsteroids();
186+
model.checkCollision();
187+
if (model.avatar.life <=0) {
188+
model.gameState = States.GAMEOVER;
189+
}
140190
break;
141191
}
142192
break;
143193
case States.GAMEOVER:
194+
switch (event) {
195+
case Events.START:
196+
model.init();
197+
model.gameState = States.PLAYING;
198+
}
144199
break;
145200
}
146201

147202
this.view.update(model, event);
148203
}
149-
150-
guessHandler( guessText ) {
151-
q(Events.GUESS, guessText);
152-
}
153204
}
154205

155206

@@ -161,12 +212,38 @@ model.init();
161212
var control = new Control();
162213

163214
var gameroot = document.getElementById("#gamecontainer");
164-
var view = new View(gameroot)
165-
view.addButtonListener(control.guessHandler);
215+
var view = new View(gameroot, model)
166216
control.setView(view);
167217

168218
function q(event, data) {
169219
setTimeout(control.fsm, 0, model, event, data);
170220
}
171221

172-
control.fsm(model, Events.START, {});
222+
//control.fsm(model, Events.START, {});
223+
224+
setInterval(() => {
225+
q(Events.TICK, {});
226+
227+
}, 50)
228+
229+
/**** Goofing around *****/
230+
document.addEventListener("keydown", (event) => {
231+
switch (event.code) {
232+
case "KeyD":
233+
case "KeyA":
234+
model.setKey(event.code, true);
235+
break;
236+
case "Space":
237+
q(Events.START, {});
238+
break;
239+
}
240+
})
241+
242+
document.addEventListener("keyup", (event) => {
243+
switch (event.code) {
244+
case "KeyD":
245+
case "KeyA":
246+
model.setKey(event.code, false);
247+
break;
248+
}
249+
})

style/style.css

+46
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,49 @@ body {
22
background: black;
33
color: lime;
44
}
5+
6+
header {
7+
margin:auto;
8+
width: 30%;
9+
top: 30vh;
10+
text-align: center;
11+
}
12+
13+
footer {
14+
margin:auto;
15+
width: 30%;
16+
top: 30vh;
17+
text-align: center;
18+
}
19+
20+
.spaceship {
21+
position: absolute;
22+
width: 5vw;
23+
left: 50vw;
24+
top: 80vh;
25+
}
26+
27+
.spaceship img {
28+
width: 100%;
29+
}
30+
31+
.starfield {
32+
position: absolute;
33+
top: 0;
34+
left: 0;
35+
width: 100vw;
36+
height: 100vh;
37+
z-index: -1;
38+
background-image: url("../images/space5.png");
39+
background-repeat: repeat;
40+
background-position: 0 0;
41+
}
42+
43+
.asteroid {
44+
position: absolute;
45+
width: 20vw;
46+
}
47+
48+
.asteroid img {
49+
width: 100%;
50+
}

0 commit comments

Comments
 (0)