Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Нагаев Дмитрий #23

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": "hrundel/browser"
"extends": "hrundel/browser",
"parserOptions": {
"sourceType": "module"
}
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules/
*.log
.cache/
dist/
40 changes: 40 additions & 0 deletions drawer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import snap from 'snapsvg';

class Drawer {
drawHero() {
this.layout = snap('.hero__picture');
this.head = this.layout.circle(50, 50, 50).attr({ fill: '#C5AFA4' });
this.eyes = this.layout.group(
this.layout.circle(70, 30, 10),
this.layout.circle(30, 30, 10)
);
this.eyes.attr({ fill: '#CF4D6F' });
this.mouth = this.layout.path('M10,70C40,90,60,90,90,70').attr({ fill: '#C97282' });
this.nose = this.layout.path('').attr({ fill: '#76818E' });
this.nose = this.layout.group(
this.layout.circle(50, 50, 12).attr({ fill: '#ecc5c4' }),
this.layout.circle(44, 50, 3).attr({ fill: '#b85f69' }),
this.layout.circle(56, 50, 3).attr({ fill: '#b85f69' }),
);
}

animateDeath() {
this.stopSpeak();
this.eyes.attr({ fill: '#000' });
this.mouth.animate({ d: 'M10,90C40,70,60,70,90,90' }, 1000);
}

stopSpeak() {
if (this.ears) {
this.ears.attr({ opacity: 0 });
}
}

startSpeak() {
this.ears = this.layout.group(this.layout.polygon([4, 30, 30, 4, 0, 0]),
this.layout.polygon([96, 30, 70, 4, 100, 0]));
this.ears.attr({ fill: '#b85f69' });
}
}

export default new Drawer();
206 changes: 206 additions & 0 deletions hrunogochi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import { emptyHandler, bounded } from './utils';

const TICK_INTERVAL = 1500;

const phrases = [
'Хрю-хрю',
'Поиграй со мной',
'Эх...'
];

export default class Hrunogochi {
constructor(state) {
this._init(state);
this._onStart = emptyHandler;
this._onReset = emptyHandler;
this._onUpdate = emptyHandler;
this._onSpeak = emptyHandler;
this._onDeath = emptyHandler;
}

_init(state) {
this._state = state || this._getInitialState();
this._eating = false;
this._sleeping = false;
this._speaking = false;
}

get isDead() {
const { satiety, energy, mood } = this;

return [satiety, energy, mood].filter(value => value === 0).length > 1;
}

get eating() {
return this._eating;
}

set eating(value) {
this._eating = value;
}

get sleeping() {
return this._sleeping;
}

set sleeping(value) {
this._sleeping = value;
}

get speaking() {
return this._speaking;
}

set speaking(value) {
this._speaking = value;
}

get energy() {
return this._state.energy;
}

set energy(value) {
this._state.energy = bounded(value);
}

get satiety() {
return this._state.satiety;
}

set satiety(value) {
this._state.satiety = bounded(value);
}

get mood() {
return this._state.mood;
}

set mood(value) {
this._state.mood = bounded(value);
}

get state() {
return this._state;
}

_getInitialState() {
return {
satiety: 100,
energy: 90,
mood: 75
};
}

_setState({ satiety, energy, mood }) {
this.satiety = satiety;
this.energy = energy;
this.mood = mood;

this.onUpdate();
}

_updateState(newState) {
const mergedState = Object.assign({}, this._state, newState);
this._setState(mergedState);
}

speak(text) {
this.onSpeak({ text });
}

saveState(saveAction) {
saveAction(this._state);
}

start() {
// eslint-disable-next-line max-statements
const tick = () => {
if (this.isDead) {
this.onDeath();

return this.stop();
}

if (Math.random() > 0.75) {
const chosenPhrase = phrases[Math.floor(Math.random() * phrases.length)];
this.speak(chosenPhrase);
}

let { satiety, energy, mood } = this;

if (this.speaking) {
mood += 3;
} else if (this.sleeping) {
energy += 3;
} else if (this.eating) {
satiety += 3;
}

satiety--;
energy--;
mood--;

this._updateState({
satiety,
energy,
mood
});

this._tickId = setTimeout(tick, TICK_INTERVAL);
};

tick();
this.onStart();
}

stop() {
clearTimeout(this._tickId);
}

reset() {
this.onReset();
this.stop();
this._setState(this._getInitialState());
this.start();
}

get onStart() {
return this._onStart;
}

set onStart(handler) {
this._onStart = handler;
}

get onUpdate() {
return this._onUpdate;
}

set onUpdate(handler) {
this._onUpdate = handler;
}

get onReset() {
return this._onReset;
}

set onReset(handler) {
this._onReset = handler;
}

get onSpeak() {
return this._onSpeak;
}

set onSpeak(handler) {
this._onSpeak = handler;
}

get onDeath() {
return this._onDeath;
}

set onDeath(handler) {
this._onDeath = handler;
}
}
50 changes: 50 additions & 0 deletions index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
html,
body
{
margin: 0;
padding: 0;
height: 100%;
}

body
{
display: flex;
}

.game
{
width: 30%;
margin: auto;
}

.state,
.controls
{
display: flex;
}

.state-item,
.controls-item
{
flex-grow: 1;
text-align: center;
}

.controls-item
{
padding: 5px 10px;
font-size: 15px;
}

.hero
{
margin: 10px;
display: flex;
flex-direction: column;
align-items: center;
}

.hero__speech
{
margin: 10px;
}
25 changes: 25 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,32 @@
<meta charset="utf-8">
<title>Хрюногочи</title>
<link rel="stylesheet" href="./index.css">
<script defer type="text/javascript" src="./index.js"></script>
</head>
<body>
<div class="game">
<div class="state">
<div class="state-item satiety">
<span class="state-item__name">Cытость</span>: <span class="state-item__value">0</span>%
</div>
<div class="state-item energy">
<span class="state-item__name">Энергия</span>: <span class="state-item__value">0</span>%
</div>
<div class="state-item mood">
<span class="state-item__name">Настроение</span>: <span class="state-item__value">0</span>%
</div>
</div>

<div class="controls">
<button class="controls-item eat">Накормить</button>
<button class="controls-item reset">Начать заново</button>
<input class="controls-item volume" type="range">
</div>

<div class="hero">
<svg class="hero__picture" width="100" height="100"></svg>
<div class="hero__speech">Я готов поговорить</div>
</div>
</div>
</body>
</html>
Loading