Пятница, время расслабляющих статей… Я решил написать эту статью благодаря хабровчанину TheShock и благодаря человеку, написавшему в своё время LOOT-RPG.
Как собственно я делал игру, можно прочитать под катом.
Открыв курс по JS на codeacademy, я дошел до простых структур данных и мне наскучило. А что если не выполнить скучные задания, а сделать свою собственную игру с блекджеком и девицами, примерно как в первом примере? Сказано — сделано…
Надо было определиться с жанром. Больше всего на свете я люблю стратегии, чуть меньше — RPG. Значит выбираем стратегии. Что у нас будет? Будет город и его менеджмент. Что-то в духе Townsmen/Travian.
Для начала нам нужен город. Рисуем что-нибудь в духе пустого пейзажа города Heroes или пустого пейзажа неотсроенного города Travian.
Объявляем переменные и инициируем их:
Вуаля, в нашем городе начальное население, какая-никакая казна, а также нулевой уровень трех доступных построек и ноль городовых. Поскольку наша игра будет не пошаговой, а в режиме реального времени, то зададим таймер, по которому у нас будет прирост ресурсов:
Внимательные читатели обратят внимание на updateResources() и вот его код:
Давайте уже что-нибудь построим по нажатию кнопки
}
Отрисовка сделана на Canvas. Это, пожалуй, одна из немногих вещей, которая не пахнет нафталином во всем этом коде. Однако код может многим показаться странным, хоть и неоднократно приведен в разных местах в качестве примера:
Сохранения храним в локальном хранилище. Честно, это удобнее, чем работать с куками, но и менее универсально. Хотя с момента, когда я переписал большую часть графика на Canvas, это стало не принципиальным: старые браузеры одинаково не поддерживают и Canvas и localStorage.
Этой статьей я хотел показать, что если вашей давней мечтой является создание пусть простенькой, но своей игры (и не «3 в ряд»), то всё в ваших руках. Я выбрал JavaScript для этой задачи, потому что браузер есть почти везде, а значит почти везде я смогу играть в свою игру, и мне для этого не потребуется подключение к интернету. Браузер стал универсальной средой исполнения, а не просто программой для отображения контента. Благодаря небольшим переделкам, игру можно стилизовать под те или иные требования, добавить тот или иной функционал, расширить как угодно. Главное — это ваша фантазия, а значит всё в ваших руках. Когда я создавал свой проект, я старался как можно дольше не использовать зависимости, и на текущий момент моя игра пока не использует никаких внешних зависимостей.
P.S.: размещая проект на гитхабе и устанавливая метки (labels), я натолкнулся на проект, где автор кроме того как программирует, еще и обладает художественным вкусом, однако общая идея похожа.
P.P.S.: любые замечания приветствуются)
Как собственно я делал игру, можно прочитать под катом.
Открыв курс по JS на codeacademy, я дошел до простых структур данных и мне наскучило. А что если не выполнить скучные задания, а сделать свою собственную игру с блекджеком и девицами, примерно как в первом примере? Сказано — сделано…
Надо было определиться с жанром. Больше всего на свете я люблю стратегии, чуть меньше — RPG. Значит выбираем стратегии. Что у нас будет? Будет город и его менеджмент. Что-то в духе Townsmen/Travian.
Для начала нам нужен город. Рисуем что-нибудь в духе пустого пейзажа города Heroes или пустого пейзажа неотсроенного города Travian.
Объявляем переменные и инициируем их:
var gold = 20;
var pop = 2;
var buildLevelD = 0;
var buildLevelH = 0;
var buildLevelTreasury = 0;
var treasuryGuard = 0;
updateResources();
Вуаля, в нашем городе начальное население, какая-никакая казна, а также нулевой уровень трех доступных построек и ноль городовых. Поскольку наша игра будет не пошаговой, а в режиме реального времени, то зададим таймер, по которому у нас будет прирост ресурсов:
setInterval(resourcesTimer, 30000);
function resourcesTimer() {
gold = gold*1+pop*1;
if (pop < 2*Math.pow((buildLevelH*1+3),2)) {
pop = pop*1+1;
}
if (treasuryGuard > 0) {
if (gold - treasuryGuard * treasuryGuardPricePayroll >= 0) {
gold = gold - treasuryGuard * treasuryGuardPricePayroll;
} else {
treasuryGuard = 0;
}
}
updateResources();
}
Внимательные читатели обратят внимание на updateResources() и вот его код:
function updateResources() {
document.getElementById("gold").innerHTML = gold;
document.getElementById("pop").innerHTML = pop;
document.getElementById("treasuryGuard").innerHTML = treasuryGuard;
}
Давайте уже что-нибудь построим по нажатию кнопки
<button id="treasury" onclick="Build('Treasury')" class="interface" style="top:250px; left:20px">Build treasury: 20 gold</button>
function Build(Structure) {
if (Structure==="Wall" || Structure ==="Tower") {
if (gold >= costWall && buildLevelD == 0) {
buildLevelD = buildLevelD*1 + 1;
gold = gold - costWall;
redraw = 1;
whatDraw = "Wall";
updateResources();
return true;
}
if (gold >= costTower && buildLevelD == 1) {
buildLevelD = buildLevelD*1 + 1;
gold = gold - costTower;
redraw = 1;
whatDraw = "Tower";
updateResources();
return true;
}
}
if (Structure==="Home") {
if (gold >= Math.pow(costHome,(buildLevelH*1 + 1))) {
gold = gold - Math.pow(costHome,(buildLevelH*1 + 1));
redraw = 1;
whatDraw = "Home";
buildLevelH = buildLevelH*1 + 1;
updateResources();
return true;
}
}
if (Structure==="Treasury") {
if (gold >= Math.pow(costTreasury,(buildLevelTreasury*1 + 1))) {
gold = gold - Math.pow(costTreasury,(buildLevelTreasury*1 + 1));
redraw = 1;
whatDraw = "Treasury";
buildLevelTreasury = buildLevelTreasury*1 + 1;
updateResources();
return true;
}
}
}
Отрисовка сделана на Canvas. Это, пожалуй, одна из немногих вещей, которая не пахнет нафталином во всем этом коде. Однако код может многим показаться странным, хоть и неоднократно приведен в разных местах в качестве примера:
function composite() {
imagesLoaded = imagesLoaded*1 + 1;
if (imagesLoaded > 1) {
// composite now
//ctx.globalAlpha = 1.00;
ctx.drawImage(img1, 0, 0); //draw background
ctx.drawImage(img2, 0, 0); //draw sawmill
ctx.drawImage(img3, 10, 40); //draw gold icon
ctx.drawImage(img4, 10, 80); //draw pop icon
ctx.drawImage(img8, 0, 0); //draw wishing well
if (buildLevelD > 0) {
// draw back piece of wall
ctx.drawImage(img6_1, 0, 0);
}
if (buildLevelH > 0 && buildLevelH < 10) {
// draw houses
ctx.drawImage(img5, 0, 0);
}
if (buildLevelH > 10) {
// draw more houses
ctx.drawImage(img5_1, 0, 0);
}
if (buildLevelD > 1) {
// draw castle
ctx.drawImage(img7, 0, 0);
}
if (buildLevelD > 0) {
// draw front piece of wall
ctx.drawImage(img6_2, 0, 0);
}
if (buildLevelTreasury > 0) {
// draw treasury
ctx.drawImage(img9, 0, 0);
}
}
}
function loadImage(src, onload) {
var img = new Image();
img.onload = onload;
img.src = src;
return img;
}
Сохранения храним в локальном хранилище. Честно, это удобнее, чем работать с куками, но и менее универсально. Хотя с момента, когда я переписал большую часть графика на Canvas, это стало не принципиальным: старые браузеры одинаково не поддерживают и Canvas и localStorage.
function saveGame() {
localStorage.setItem('gold', gold);
localStorage.setItem('pop', pop);
localStorage.setItem('buildLevelD', buildLevelD);
localStorage.setItem('buildLevelH', buildLevelH);
localStorage.setItem('treasuryGuard', treasuryGuard);
localStorage.setItem('buildLevelTreasury', buildLevelTreasury);
}
function loadGame() {
gold = localStorage.getItem('gold');
pop = localStorage.getItem('pop');
buildLevelD = localStorage.getItem('buildLevelD');
buildLevelH = localStorage.getItem('buildLevelH');
treasuryGuard = localStorage.getItem('treasuryGuard');
buildLevelTreasury = localStorage.getItem('buildLevelTreasury');
composite();
updateResources();
}
Этой статьей я хотел показать, что если вашей давней мечтой является создание пусть простенькой, но своей игры (и не «3 в ряд»), то всё в ваших руках. Я выбрал JavaScript для этой задачи, потому что браузер есть почти везде, а значит почти везде я смогу играть в свою игру, и мне для этого не потребуется подключение к интернету. Браузер стал универсальной средой исполнения, а не просто программой для отображения контента. Благодаря небольшим переделкам, игру можно стилизовать под те или иные требования, добавить тот или иной функционал, расширить как угодно. Главное — это ваша фантазия, а значит всё в ваших руках. Когда я создавал свой проект, я старался как можно дольше не использовать зависимости, и на текущий момент моя игра пока не использует никаких внешних зависимостей.
P.S.: размещая проект на гитхабе и устанавливая метки (labels), я натолкнулся на проект, где автор кроме того как программирует, еще и обладает художественным вкусом, однако общая идея похожа.
P.P.S.: любые замечания приветствуются)
Поделиться с друзьями
sinneren
Ну, пошла жара:
Почему строения константой? Почему ресурсы начальные не в одном объекте? Где вообще какой-то ООП? Где база архитектуры игры, почему сразу о ресурсах? И самое главное — где игра-то? Ссылка на чужую есть, а от своей какие-то огрызки кода и всё.
Areso
Отвечаю по порядку. Это не константы (уж точно нет). Начальные и не начальные (сэйв, лоад) ресурсы не в одном объекте, потому что я хотел это сделать (подглядев из примера LOOT-RPG) и забыл, занимаясь другими задачами (когда нужно больше зданий, больше случайных событий, немного было не до переписывания того, что уже работает). Так уж получилось, что я не фанат ООП, и пишу в процедурном стиле, где это возможно. Это простая игра, здесь не было острой необходимости в ООП. Архитектуру игры я пытался некоторое время поддерживать в yEd, но потом схема безнадежно отстала от реальности.
Вот игра, которую я нашел по меткам. Вот Моя игра, но я не хотел её показывать по причине очень жуткой самодельной графики (к сожалению, я не художник и не смог найти никого, кто бы вызвался помочь с графикой на добровольных началах, а собрать из PD0 ресурсов нормальный набор мне не удалось).
GrimMaple
Я тоже не особый фанат ООП, но избегать ОО в явно объектной задаче как минимум странно. В играх любой сложности объектная ориентированность (?) сильно упрощает жизнь.