![]() |
|
||||||||||
|
|||||
|
Цитата:
|
|
|||||
|
Регистрация: Dec 1999
Адрес: Магадан
Сообщений: 763
|
По теме, вот мой простой и надёжный способ синхронизации между двумя игроками на основе getTimer() - синхронизируем все события относительно количества пройденных миллисекунд одного из игроков (в дальнейшем "мастера"). AS 3, вполне рабочий код - вставить в первый фрейм и скомпилировать:
import flash.*;
var connection:NetConnection;
var game_so:SharedObject;
// количество циклов для синхронизации:
var so_cycles:int = 12;
NetConnection.defaultObjectEncoding = flash.net.ObjectEncoding.AMF0;
SharedObject.defaultObjectEncoding = flash.net.ObjectEncoding.AMF0;
// имена игроков берутся из передаваемых переменных login и adv, этот код для тестирования на локальной машине (чтобы имена были разные):
if (loaderInfo.parameters.login==null) {
var mySo = SharedObject.getLocal("testname");
if (mySo.data.name == "player1") {
login = "player2"
adv = "player1";
}else{
login = "player1"
adv = "player2";
}
mySo.data.name = login;
mySo.flush();
delete mySo;
} else {
login = loaderInfo.parameters.login;
adv = loaderInfo.parameters.adv;
}
// определяем кто будет мастер (по чьему таймлайну будут синхронизироваться все события в игре (самый тупой способ):
var so_main:Boolean = login>adv;
// чтобы каждая пара игроков (имена уникальны на сервере) получала уникальный sharedoject в пользование:
var so_name:String = so_main?login+"__"+adv:adv+"__"+login;
// переменная, которая будет определять сдвиг времени для событий, чтобы привести их к таймлайну мастера (у мастера это значение останется нулём):
var timeShift:Number = 0;
var timeShiftStat:Array = new Array(so_cycles);
connection = new NetConnection();
connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
connection.connect("rtmp://[ваше приложение]");
function netStatusHandler(event:NetStatusEvent):void {
switch (event.info.code) {
case "NetConnection.Connect.Success":
connectSO();
break;
case "NetConnection.Connect.Failed":
trace("failed");
break;
}
}
function connectSO () {
game_so = SharedObject.getRemote(so_name, connection.uri, false);
if(game_so){
game_so.addEventListener(SyncEvent.SYNC, soOnSync);
// нужно, если игроки могут присоединяться по локальной сети (маленький пинг):
game_so.fps = 1000;
game_so.connect(connection);
}
}
function soOnSync(event:SyncEvent):void {
if (game_so.data.ts == null) {
if (!so_main) {
// начинает синхронизацию слейв, путём инициализации значения ts.n нулём:
game_so.setProperty("ts",{n:0,t:getTimer()});
}
} else {
if (game_so.data.ts.n<so_cycles) {
// в массиве сохраняем время каждого события синхронизации:
timeShiftStat[game_so.data.ts.n] = game_so.data.ts.t;
// четные значения посылаются слейвом, нечётные мастером:
if (game_so.data.ts.n%2 ^ so_main) {
game_so.setProperty("ts",{n:game_so.data.ts.n+1,t:getTimer()});
}
} else {
calculateTimeShift();
}
}
}
// подсчитаем сдвиг времени для слейва:
function calculateTimeShift () {
var arr:Array=[];
for (var i:int=1; i<so_cycles-2; i+=2) {
arr.push((timeShiftStat[i+2]+timeShiftStat[i])/2-timeShiftStat[i+1]);
}
// для небольшой дисперсии вполне хватает такого тривиального выбора среднего (для более точного подсчёта можно вычислять равноудалённое, среднее арифметическое, и не забыть отбросить слишком большие и слишком маленькие значения):
arr.sort();
timeShift = arr[Math.floor(arr.length/2)];
}
Несимметричный метод (когда есть выделеный игрок, относительно таймлайна которого синхронизируются остальные) хорош тем, что может быть легко адаптирован для большего числа игроков (и наблюдателей игры - которые не влияют на события, но могут видеть). Достаточно синхронизировать свой таймлайн с мастером. Метод удобен для игр, где есть объекты, которые движутся по заданным тракториям, пока на них не подействует один из игроков, когда не надо постоянно транслировать картину игры друг другу (аркады очень многие, мноопользовательские рпг, разбитые на локейшоны). Достаточно передавать изменения и новую траекторию объекта. Эти объекты синхронизируются идеально (у меня получается разница порядка 10миллисекунд при пингах в районе 300-500, это значит, например, что поставив два компьютера рядом, и законнектив их через сервер на другом полушарии, вы не сможите увидеть разницу в движении независимых объектов). Проблема, естественно, остаётся с объектами, контролируемыми игроками, при пинге порядка полусекунды, если мы будем просто транслировать текущие координаты - будет заметно дёрганье, но тут есть хитрость: для этих объектов можно использовать различные алгоритмы компенсации, в самом простом случае передаём кроме положения ещё и скорость объекта. Пока не поступили новые данные, движим объект равномерно и прямолинейно. Как только поступили новые координаты удалённого игрока - не перемещаем объект сразу в место, где он должен быть, а делаем это плавно, в течении, скажем 300 миллисекунд - это существенно сгладит рывки объекта. В идеале оперировать надо кроме положения и скорости ещё и ускорением, чтобы вторая производная тоже была гладкой - тогда рывков вообще не будет заметно и будет полное впечатление, что синхронизация постоянная, как на локальной машине. Да, при таком "размытом" определении положения объекта игрока не сделать какое-нибудь полноконтактное взаимодействие (сложный фехтовальный бой или что-то вроде мортал комбата - но это проблема не только во флэше) - просто не будет хватать передаваемых данных, интерактивности взаимодействия.Ещё приведённый выше кода и подход в целом хорош тем, что не требует никакой серверной части, скажу больше: он даже не требует своего сервера, ведь нужно только права открывать свои шареные обжекты, достаточно присоединиться к любому rtmp приложению, открытому в веб (к примерам на Адобе или на сервере примеров red5 Но так делать нехорошо, разве что для теста...). Вся обработка событий вынесена на сторону клиента, поэтому скорость симметрична относительно разницы пинга игроков, фактически работаем с суммой пингов, это обеспечивает один из условий fairplay (игрок с маленьким пингом не имеет преимущества перед игроком с большим пингом).Вот ещё картинка, поясняющая, как мы считаем timeShift (в данном случае первым было запущено приложение слэйва (на рисунке справа), он установил значение t0 и ждёт, кода мастер (слева на временной шкале) продолжит синхронизацию. timeShift в этом примере получится отрицательным и равным (3200+2000)/2-9150= -6550 (т.е. по усреднению выборки считаем, что событие t4 у слэйва произошло в точности посередине событий t3 и t5 у мастера). Черные точки на линиях показывают, в какой момент событие может доходить до сервера и почему это не влияет на вычисления (из симметрии).
__________________
Верить никому нельзя. Мне - можно. :) |
|
|||||
|
Регистрация: Dec 1999
Адрес: Магадан
Сообщений: 763
|
Но это так, вкратце, тема-то неисчерпаемая
![]()
__________________
Верить никому нельзя. Мне - можно. :) |
|
|||||
|
Регистрация: Aug 2006
Сообщений: 70
|
Цитата:
http://www.gamedev.ru/code/forum/?id=16529 http://www.gamedev.ru/code/forum/?id=50394 и т.д. |
|
|||||
|
Регистрация: Aug 2006
Сообщений: 18
|
по моему вопросу ответьте плиз!
|
|
|||||
|
Регистрация: Aug 2006
Сообщений: 18
|
Спасибки всем! Бду пробовать разные методы
|
|
|||||
|
Цитата:
__________________
(А) |
|
|||||
|
Квач
Регистрация: Sep 2006
Адрес: Украина, Киев
Сообщений: 1,526
|
2 Kyber Anton:
Я не писал, что игры невозможно делать на Флеше. Это было бы глупо с моей стороны, поскольку таковых бесчисленное множество. Но я повторю, что Флеш делался не для игр. Что ни говорите, а ни один разработчик не решится создавать что-то серьёзное на Флеше. Слишком медленная тут графика. Я искренне люблю Флеш и если бы он был девушкой, наверное, я бы на нём женился, но стоит смотреть правде в глаза... Флеш - отличная вещь и границы его применения широки, но не стоит считать, что он удобен для создания игр и для этого создавался. Да, может удобен... Как и любой движок со Scene-Graph...И то, для чего-то маленького... А из-за того, что флешки работают по-разному не только на разных компьютерах, но и под разными броузерами, согласитесь, лучше он не становится...
__________________
Да не нужно тебе читать документацию по Flash и AS от Adobe - ты слишком умён для этого |
|
|||||
|
Цитата:
И игры писать на флеше можно, если правильно работать с битмапдатами, всё можно. Может не таике крутые и быстрые как на Си, но можно же. Стратегу типа первого варкрафта точно можно написать. Последний раз редактировалось miramax; 05.10.2006 в 23:17. |
![]() |
![]() |
Часовой пояс GMT +4, время: 14:15. |
|
|
« Предыдущая тема | Следующая тема » |
|
|