Skip to content

Commit c5bda6d

Browse files
authored
Merge pull request #9 from itsdorosh/small-fixes-before-second-gen
prep for second gen
2 parents 16ef8af + 9f0b887 commit c5bda6d

28 files changed

+737
-681
lines changed

.editorconfig

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
# Editor configuration, see http://editorconfig.org
1+
# https://editorconfig.org
22
root = true
33

44
[*]
55
charset = utf-8
6-
indent_style = tab
6+
end_of_line = lf
77
indent_size = 2
8+
indent_style = space
89
insert_final_newline = true
9-
end_of_line = lf
10+
max_line_length = 120
1011
trim_trailing_whitespace = true
1112

1213
[*.md]

README.md

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,53 @@
11
# emoji-shooter
2-
игра, в которой нужно отстреливать различные летающие эмоджи 😈
32

4-
![pic](./preview.png)
3+
A minimalistic first-person shooter in which you have to shoot emojis flying at you. 😈
54

6-
собственно, приложение имеет максимально простую структуру:
5+
> ℹ️ Based on the classic webdev stack (html/css/js) and three.js library.
76
8-
viewer.js - отвечает за сцену, это api, которое предоставляет для всех пользователей этой зависимости следующее:
9-
- рисовать
10-
- управлять камерой
11-
- светом
12-
- рейкастером
7+
![pic](assets/emoji-shooter-preview.png)
138

14-
engine.js - отвечает за логику игры:
15-
- создание объектов
16-
- выстрелы
17-
- уничтожение объектов при попадании
18-
- звуки
19-
- набор очков
20-
- проигрыш
21-
- старт-паузу-стоп.
9+
---
2210

23-
этот слой принимает сигналы с контролов и посылает сигналы во вьювер.
11+
## Structure
2412

25-
controls.js - слой, который слушает пользовательские события и имеет событийную систему. создан для того, чтобы игровая логика, помещённая в engine могла тригерить реакции на действия пользователя.
13+
### main.js (ui)
2614

27-
raycaster.js - по сути промежуточный слой между контролами и движком, имеет api для выборки объектов по координатам, имеет фильтрацию по типам объектов, может искать в каком-то конкретном пространстве (по дефолту сцена).
15+
The upper level of the architecture, contains the initialization and launch code
16+
as well as for managing various states of the ui part (buttons, labels, etc.).
2817

29-
Детальнее на схеме:
30-
![pic](./schema.png)
18+
### engine.js
19+
20+
Responsible for the game logic:
21+
22+
- creating enemies
23+
- firing shots
24+
- destruction of enemies on hit
25+
- calculation of points for hits
26+
- game over conditions
27+
- game control: start-pause-stop
28+
29+
This layer receives events from controls and call methods of the viewer.
30+
31+
### controls.js
32+
33+
A layer that listens events from the different input sources and has an event system.
34+
35+
### viewer.js
36+
37+
API for working with the 3D part of the system:
38+
39+
- creating and deleting objects
40+
- camera movement control
41+
- lighting control on scene
42+
43+
### raycaster.js
44+
45+
API for selecting objects by coordinates, has filtering by object types,
46+
can search in a specific space (scene by default).
47+
48+
---
49+
50+
## Schema
51+
52+
See the schema for more details:
53+
![pic](./assets/emoji-shooter-schema.png)
File renamed without changes.

assets/emoji-shooter-schema.drawio

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile host="app.diagrams.net" modified="2021-05-01T15:51:16.310Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Safari/605.1.15" etag="soVUBsYrH2HkaY_zmFv_" version="14.6.9" type="device"><diagram id="Hx81tdVGdHfVVyK69G49" name="Page-1">3Vpbc5s4GP01fkwGhLn40XXsdqbtTnayO22fdmQQoFYgVojY7q9fCcQd3xI7OJsHWzq6oHxH5+iCJ8Yi2n5kMAm/Ug+RCdC87cR4mABgA0d8SmBXAJauF0DAsFdADeAJ/0YK1BSaYQ+lrYqcUsJx0gZdGsfI5S0MMkY37Wo+Je2nJjBAPeDJhaSPfsMeDwvUMbUa/4RwEJZP1jVVEsGysgLSEHp004CM5cRYMEp5kYq2C0Rk7Mq4FO1We0qrgTEU81Ma/IGTePH3EhOQ/fnp82+k/4W/3emWGhzflf8x8kQAVJYyHtKAxpAsa/QDo1nsIdmtJnJ1nS+UJgLUBfgTcb5TbMKMUwGFPCKqFG0x/66ay/QPmb43Ve5h2yh62KmMT2OuOtQdkS/GLQe7Nx4KSmnGXHQoCGpeQRYgfqDetGJNzHZEI8TZTrRjiECOn9vjgGreBVW9mhqRUOycw1TR7zMkmXqSmPKcUZL2GGzzswkxR08JzEOwESJtc+FjQhaUUJa3NXzHRa4r8FT0/Qs1StaOOTW1KvLPiHG0PRz7fqxUA0sziybKFfRSJJtaYxUWNvRlaVcKr6H3wjiaEOzDShAxZrvvZQ8y86OZqRvluTfQD3gP+gE9/TC4c2HKEbuogJDumcgeEtDMsg1odagA1xEUMM2RBQXAmILSW4ICJwpKawpKG09QxnsQlKGNSfA5W4ea36JixXCd3cNxnntEDIuQIXY7xOvaqMz3rDTDF/VQDyLHH9yEWK6D1v5lPLPyvgObEGvAMo3ptTxTt2/GM19imMpnx/HM6YnSAaNuQoxb8Uz9NIL1NsH2OyDYGNUaZ6MSXC2EZ1Dc0fA5DINxGDbHZHjaW/yWcYBj1OedEJyk6PjiB9OkuLny8VbOgp6I8rzqeGi1NJHjTYdWSwesDcu6zGppzNqrpThinHbCqMCLU2H2qJgAi3AVsRYb1r8ZLQvu0jy2c1FBB8k2D09ZLlKB/H7GaCMPhkV3YnRFj0XhK/c6HQF1L2B8HwxfwHjW2jIvxGb3vDjVxr6A0ae345yn7n4aG56RT4zOqQeHMa3TGdBrh/I0hIlM4ii/l29SJec7diGZExzEAuOS4gr9AteIPNIUc0xl6ZpyTiNRgciCD9D9FeSTpa008Seq5A+bly6sDVmyGs9DyLl88TCXgQAr14u1e+zS2MdiGrJ7VzwRrDzIofiSeCq+mYgdvROWEKVy8VhZ8uMjjNA/i+IClyB2pwPnPomDvZPkVWLXjeMHneq9Rcu6taupfdyN8MvUbt+K2mdvpPa86ZwxuGtUSCiOedro+VEC9Wyz2yuL1Xkr1altzQ5VF4ni8fVMq/6Pl0++2f/Qh8BRH1pjnmIkU7p8Kbv6SrMUXdd4ph3fMfpbRnvAduyr3Unf0Ons6KWlyLzhzWP5vv22j9flKF+75e/t94UUTt7tl96QRWTucqni4+ofNo3GJKEZJ+IUuah+xrD/rP0qSXZPcQOSLF8dhe3fNZxNqdz7VL9uKLy7/omIsfwP</diagram></mxfile>

assets/emoji-shooter-schema.png

32.4 KB
Loading

assets/favicon.ico

15 KB
Binary file not shown.

index.html

Lines changed: 22 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,130 +1,37 @@
11
<!DOCTYPE html>
22
<html lang="en">
33
<head>
4-
<meta charset="UTF-8">
5-
<title>Emoji Shooter 🔫</title>
6-
<link rel="stylesheet" href="./main.css">
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<meta name="description" content="Authors: Andrii Doroshenko (@itsdorosh) and Kate Fastovets (@katfastovets);
7+
A minimalistic first-person shooter in which you have to shoot emojis flying at you. 😈
8+
Game has support for gamepads.">
9+
<title>Emoji Shooter</title>
10+
<link rel="icon" href="assets/favicon.ico" type="image/x-icon"/>
11+
<link rel="stylesheet" href="./main.css">
712
</head>
813
<body>
9-
<div id="inGameButtons" class="position-absolute hide">
10-
<p id="pointsCount">Count: 0</p>
11-
<button id="pauseButton">Pause ⏸</button>
14+
<div id="headerContainer" class="position-absolute">
15+
<p id="pointsCount">Count: 0</p>
16+
<button id="pauseButton">Pause ⏸</button>
1217
</div>
1318

14-
<div id="gameButtons" class="position-absolute">
15-
<h1 id="greetingCaption">Emoji Shooter 🔫</h1>
16-
<h1 id="gameOverCaption" class="hide">GAME OVER</h1>
17-
<button id="playButton">Play ▶️</button>
18-
<button id="restartButton" class="hide">Restart 🔄</button>
19+
<div id="menuContainer" class="position-absolute">
20+
<h1 id="greetingCaption">Emoji Shooter 🔫</h1>
21+
<h1 id="gameOverCaption" class="hidden">GAME OVER</h1>
22+
<button id="playButton">Play ▶️</button>
23+
<button id="restartButton" class="hidden">Restart 🔄</button>
1924
</div>
2025

21-
<div id="generalButtons" class="position-absolute">
22-
<span id="fullscreenMode" onclick="toggleFullScreen()">📺️</span>
23-
<span id="gamepad" class="hide">🎮</span>
24-
<span id="mouse" class="hide">🖱</span>
26+
<div id="toolbarContainer" class="position-absolute">
27+
<button id="gamepad">🎮</button>
28+
<button id="mouse">🖱</button>
29+
<button id="fullscreen">📺️</button>
2530
</div>
2631

2732
<div id="canvasContainer"></div>
2833

29-
<script src="https://unpkg.com/[email protected]/build/three.js"></script>
30-
<script src="./src/constants.js"></script>
31-
<script src="src/enemies.js"></script>
32-
<script src="./src/helpers.js"></script>
33-
<script src="./src/controls.js"></script>
34-
<script src="./src/raycaster.js"></script>
35-
<script src="./src/viewer.js"></script>
36-
<script src="./src/engine.js"></script>
37-
38-
<script>
39-
// containers
40-
const canvasContainer = document.getElementById('canvasContainer');
41-
const inGameButtons = document.getElementById('inGameButtons');
42-
const gameButtons = document.getElementById('gameButtons');
43-
44-
// buttons
45-
const playButton = document.getElementById('playButton');
46-
const pauseButton = document.getElementById('pauseButton');
47-
const restartButton = document.getElementById('restartButton');
48-
const gamepadButton = document.getElementById('gamepad');
49-
const mouseButton = document.getElementById('mouse');
50-
51-
// captions
52-
const greetingCaption = document.getElementById('greetingCaption');
53-
const gameOverCaption = document.getElementById('gameOverCaption');
54-
55-
const viewer = new Viewer(canvasContainer);
56-
const controls = new Controls(canvasContainer);
57-
const raycaster = new Raycaster(viewer.camera);
58-
const engine = new Engine(viewer, controls, raycaster);
59-
60-
engine.onPointCountUpdate((count) => {
61-
document.getElementById('pointsCount').innerText = `Count: ${count}`;
62-
});
63-
64-
engine.onGameOver(() => {
65-
hide(greetingCaption, playButton);
66-
show(gameButtons, gameOverCaption, restartButton);
67-
});
68-
69-
playButton.addEventListener('click', () => {
70-
hide(gameButtons);
71-
show(inGameButtons);
72-
engine.play();
73-
});
74-
75-
pauseButton.addEventListener('click', () => {
76-
show(gameButtons, restartButton, playButton);
77-
engine.pause();
78-
});
79-
80-
restartButton.addEventListener('click', () => {
81-
hide(gameOverCaption, gameButtons);
82-
show(greetingCaption);
83-
engine.restart();
84-
});
85-
86-
gamepadButton.addEventListener('click', () => controls.switchControlsMode(CONTROLS_MODES.GAMEPAD_MODE));
87-
88-
mouseButton.addEventListener('click', () => controls.switchControlsMode(CONTROLS_MODES.MOUSE_MODE));
89-
90-
controls.on('gamepadconnected', () => {
91-
controls.switchControlsMode(CONTROLS_MODES.MOUSE_MODE);
92-
});
93-
94-
controls.on('gamepaddisconnected', () => {
95-
controls.switchControlsMode(CONTROLS_MODES.NO_MODE);
96-
});
97-
98-
controls.on('controlsModeSwitched', (mode) => {
99-
switch (mode) {
100-
case CONTROLS_MODES.MOUSE_MODE: {
101-
hide(mouseButton);
102-
show(gamepadButton);
103-
break;
104-
}
105-
106-
case CONTROLS_MODES.GAMEPAD_MODE: {
107-
hide(gamepadButton);
108-
show(mouseButton);
109-
break;
110-
}
111-
112-
case CONTROLS_MODES.NO_MODE: {
113-
hide(mouseButton, gamepadButton);
114-
break;
115-
}
116-
}
117-
});
118-
119-
function toggleFullScreen() {
120-
if (!document.fullscreenElement) {
121-
document.documentElement.requestFullscreen();
122-
} else {
123-
if (document.exitFullscreen) {
124-
document.exitFullscreen();
125-
}
126-
}
127-
}
128-
</script>
34+
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.js"></script>
35+
<script type="module" src="src/main.js"></script>
12936
</body>
13037
</html>

main.css

Lines changed: 57 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,86 @@
11
html,
22
body {
3-
min-height: 100%;
4-
height: 100%
3+
min-height: 100%;
4+
height: 100%
55
}
6+
7+
h1 {
8+
font-size: 60px;
9+
}
10+
611
body {
7-
margin: 0;
8-
font-family: monospace;
9-
-webkit-touch-callout: none; /* iOS Safari */
10-
-webkit-user-select: none; /* Safari */
11-
-moz-user-select: none; /* Firefox */
12-
-ms-user-select: none; /* Internet Explorer/Edge */
13-
user-select: none;
14-
overflow: hidden;
12+
margin: 0;
13+
font-family: monospace;
14+
-webkit-touch-callout: none;
15+
-webkit-user-select: none;
16+
-moz-user-select: none;
17+
-ms-user-select: none;
18+
user-select: none;
19+
overflow: hidden;
1520
}
1621

1722
button {
18-
padding: 10px 20px;
19-
border-radius: 10px;
20-
border: none;
21-
font-family: inherit;
23+
width: 160px;
24+
padding: 10px 20px;
25+
border-radius: 10px;
26+
border: none;
27+
font-family: inherit;
28+
display: flex;
29+
align-items: center;
30+
justify-content: center;
2231
}
2332

2433
#canvasContainer {
25-
height: 100%;
26-
}
27-
28-
#gameButtons {
29-
width: 100vw;
30-
height: 100vh;
31-
display: flex;
32-
align-items: center;
33-
justify-content: center;
34-
flex-direction: column;
35-
/*rebeccapurple*/
36-
background: rgba(102, 51, 153, 0.6);
34+
height: 100%;
3735
}
3836

39-
#playButton,
40-
#restartButton {
41-
display: flex;
42-
align-items: center;
43-
justify-content: center;
37+
#headerContainer {
38+
width: 100vw;
39+
height: 10vh;
40+
display: flex;
41+
align-items: center;
42+
justify-content: space-around;
43+
flex-direction: row;
44+
background: rgba(82, 115, 77, 0.6);
4445
}
4546

46-
#gameButtons button {
47-
margin-bottom: 10px;
47+
#menuContainer {
48+
width: 100vw;
49+
height: 100vh;
50+
display: flex;
51+
align-items: center;
52+
justify-content: center;
53+
flex-direction: column;
54+
background: rgba(145, 199, 136, 0.75);
4855
}
4956

50-
#inGameButtons {
51-
width: 100vw;
52-
height: 10vh;
53-
display: flex;
54-
align-items: center;
55-
justify-content: space-around;
56-
flex-direction: row;
57-
background: rgba(102, 51, 153, 0.6);
57+
#menuContainer button {
58+
margin-bottom: 10px;
5859
}
5960

60-
#generalButtons {
61-
display: flex;
62-
right: 10px;
63-
bottom: 10px;
64-
font-size: 24px;
61+
#toolbarContainer {
62+
display: flex;
63+
right: 10px;
64+
bottom: 10px;
65+
font-size: 24px;
6566
}
6667

67-
#generalButtons span {
68-
margin-left: 15px;
68+
#toolbarContainer button {
69+
width: 40px;
70+
margin-left: 15px;
6971
}
7072

7173
.aim {
72-
font-size: 72px;
73-
margin: 0;
74-
padding: 0;
75-
line-height: 0;
74+
font-size: 72px;
75+
margin: 0;
76+
padding: 0;
77+
line-height: 0;
7678
}
7779

7880
.position-absolute {
79-
position: absolute;
81+
position: absolute;
8082
}
8183

82-
.hide {
83-
display: none !important;
84+
.hidden {
85+
display: none !important;
8486
}

schema.png

-33.1 KB
Binary file not shown.

0 commit comments

Comments
 (0)