Написание клиента-бота для schemaverse

от автора

image На хабре уже было упоминание о SQL играх. Но я все был занят и только недавно решил разобратся что-же это такое. Совершенно случайно я выбрал schemaverse о которой тоже уже упоминалось на хабре.

Насколько я понял, все удовольствие от игры получаешь, когда пишешь для нее бота. Для этого я выбрал один из самых своих любимых языков — javascript. Также я решил визуализировать карту, чтобы видеть как мои кораблики летают и захватываюи вражеские планеты. Много кода и SQL запросов я приводить не буду чтобы не раздувать статью, вы всегда можете посмотреть их в репозитории.

Алгоритм поведения бота я выбрал очень простой — построить добытчиков, построить захватчиков, и когда захватчиков станет достаточно — лететь захватывать. Еще, по ходу, строятся инженеры, которые ремонтируют корабли и, если хватает денег, я провожу апгрейд флота.

С самого начала я решил по минимуму использовать сторонние библиотеки. Итак, сначала устанавливаем соединение с базой.

var config = require('./config.js');  // Postgres connection var pg = require('pg'),     conn = "pg://"+config.username+":"+config.password+"@db.schemaverse.com:5432/schemaverse";  var UserModel = require('./models/user'); var CommandProcessor = require('./command_processor');         pg.connect(conn, function(err, client) {     if (!err){         var userModel = new UserModel.constructor(client);         CommandProcessor(userModel);     } else {         console.log(err);     } }); 

После установки соединения инициализируется пользователь и чтобы можно было смотреть некоторую статистику в консоле и запускать визуализатор я добавил обработчик команд.
При инициализации пользователя собирается информация о его планетах. Посройка добытчиков/захватчиков/инженеров производит каждая планета сама для себя. А заправка/апгрейд для всех кораблей.
Это пошаговая стратегия, причем зависимость длительности хода я так и не смог проследить. Поэтому я проверяю, завершился ли ход, в зависимости от длительности предыдущего хода. В начале нового хода, проверяется состояние кораблей и вызываются обработчики, что подписались на событе «tic». Информация о захвате новой планеты получается из списка ивентов. Для того, чтобы захватить планету достаточно успешно добыть из нее топливо. Это единственный ресурс игры. Также при каждом ходе поправляется курс и скорость всех летящих кораблей.
При захвате новой планеты, она добавляется в список планет и подписывается на событие «tic».

var tick = function(){     repair_damaged();     create_miners();     create_attackers();     go_to_conqueror();  }  //constructor user.on(tick); 

Следить за всем этим по выводу консоли не очень интересно. Я добавил модуль CommandProcessor с помощью которого можно в любой момент проверить состояние игры. В любой момент можно расширить список поддерживаемых команд. Но более подробно я хочу расказать о визуализаторе и о проблемах, с которыми мне пришлось столкнутся.

После ввода команды «map» первым делом создаются веб и websocket серверы.

var app = require('http').createServer(handler), 			io = require('socket.io').listen(app, { log: false }); 

Визуализатор также подписывается на событие «tic» и передает сообщение клиентам, что можно обновить карту.
По сути веб-сервер нужен только для передачи статики, тоесть websocket клиента.
Существующие визуализаторы отображают только общую карту. Моей же целью было отображение, также, флота.

Выглядит это примерно так:
image
Я сделал при приближении кружочки планет больше, потому что они закрывались кораблями.

В наибольшем масштабе карта очень долго обновляется. Если ее перемещать или увеличивать тоже приходится долго ждать. Я не обновляю карту при каждом чихе, а жду, пока пользователь введет новые желаемые координаты. Карта реагирует на колесо мыши и перемешение. Клиент передает степень увеличения, смещение и размер требуемого рисунка. Сервер, на основе этих данных, запрашивает с базы обьекты, рисует их на canvas и передает обратно клиенту.

get_map_base64( 	data.x, 	data.y, 	data.w, 	data.h, 	data.zoom, 	data.render_planets, 	data.render_ships, 	function(img){ 		socket.emit('draw', img); 	} ); 

В теории сервер может рисовать только корабли или только планеты, но я пока это не использую.

Можно было оптимизировать скорость обновления карты, если: хранить список планет локально и изменять отдельние планеты по событию «conquer», и если брать не все карты из базы, а разбить на квадраты и брать по одной с квадрата.
Но их очень много чтобы хранить локально, я решил сэкономить память, а если брать по одной с квадрата, то при большом масштабе можно не увидеть свою начальную планету. Поэтому я решил пока не оптимизировать процес. К тому же, при большом увеличении все обновляется довольно быстро.

Ссылка за репозиторий проекта — https://github.com/peinguin/schemaverse_bot

ссылка на оригинал статьи http://habrahabr.ru/post/195322/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *