Противник двигает обещание в сетевой игре
Я провел последние четыре дня, изучая обещания, сопрограммы, волокна, продолжения и т. Д.
Я до сих пор не могу понять, как решить мои пошаговые ходы карточных игр в многопользовательском режиме, в которых начинающий игрок фактически является "игровым" контролером "до пяти, будь то ИИ или человек-игрок.
Код ниже работает, но есть одна проблема:
он не может обнаружить движения карт оппонента и поэтому продолжает играть без них, что, конечно, создает беспорядок.
Может кто-нибудь предложить, пожалуйста, изменение моей общей концепции или способ использования обещания или одну из других "синхронизирующих" конструкций?
Вот четыре ключевых области моего кода:
function oppoPlays () {
// can only go through here if game starter
if (joiner!="") {return;}
for (pp=1; pp<numberofplayers; pp++) {
if (oppoType[pp] == "AI") {
// an AI player moves
.
.
} else {
// non-AI player
var yourTurnmsg="It's "+playerNames[pp]+"'s turn";
// tell human player that it's their turn
$("#text_message").val(yourTurnmsg).trigger(jQuery.Event('keypress', { keyCode: 13, which: 13 }));
// how to detect human oppo's card moved?
}
}
}
// chat functionality
$("#text_message").on("keypress", function(e) {
if (e.keyCode == 13){
payload = new Object();
payload.action = 'chat_text';
payload.chat_text = tmsg; // It's michael29's turn
payload.user_id = playerNames[pp];
payload.game_no = game_no;
socket.send(JSON.stringify(payload));
}
});
// socket gets oppo's response
function checkJson(res, sttr_id, game_no) {
if(res.action=="game_move"){
// find player
var pp=playerNames.indexOf(res.user_id);
cpos=res.cardno;
playCard_oppo(pp, cpos);
}
}
// turn an oppo's card face up and update scores
function playCard_oppo(pp, cardno) {
// and move it to the stack
topoc= parseInt($("#oppo_card" + cardno).css('top'));
leftoc=parseInt($("#oppo_card" + cardno).css('left'));
$("#oppo_card" + cardno).css({ top: topoc, left: leftoc, opacity: "50%" });
.
.
if (joiner=="") {
// tell oppoPlays fn that the card has moved
}
}
Игра похожа на концепцию uno, но с компонентом выигрыша
(направлено на то, чтобы помочь детям с основной арифметикой).
3 ответа
Подумайте о наличии состояния доски, которое является глобальным, и ходы игрока / ИИ изменяют его. Затем, когда пришло время для противника ИИ сделать ход, он проверяет текущее состояние доски и решает ход.
Если ваше состояние доски просто представлено элементами на странице, вам потребуется способ его сканирования и вычисления полезного представления состояния платы в памяти. Без деталей вашей реализации трудно быть более конкретным.
Решение основывалось на двух вещах:
отделение кода AI-игрока от кода игрока-человека;
добавление и удаление события окна, которое срабатывает после обнаружения движения человека.
Сокращенный код теперь выглядит так:
// if this is game starter give each player a turn
if (joiner == "") {
// there's always at least one
pp = 1;
if (oppoType[pp] == "AI") { AIplays(); } else { humanPlays(); }
}
function humanPlays () {
// tell human player that it's their turn
var yourTurnmsg="It's "+playerNames[pp]+"'s turn"
$("#text_message").val(yourTurnmsg).trigger(jQuery.Event('keypress', { keyCode: 13, which: 13 }));
//window.addEventListener("humanPlayed", function(evnt) {
$(window).on("humanPlayed", function(evnt) {
endOfTurn();
});
}
function endOfTurn () {
if (!(winner)) {
if (pp++ != numberofplayers) {
if (oppoType[pp] == "AI") {
setTimeout(function (){ $("#clickForNextPlayer").show(); }, 1000);
} else {
$("#clickForNextPlayer").trigger('click');
}
}
}
}
// click for next player
$("#clickForNextPlayer").on('click', function() {
$("#clickForNextPlayer").hide();
$(window).off("humanPlayed");
if (pp == numberofplayers) {
// uncover outStack for game starter to play
$("#outStackcover").hide();
return;
}
if (oppoType[pp] == "AI") { AIplays(); } else { humanPlays(); }
});
function AIplays () {
AIcardno = chooseCard(pp, diffLevel);
.
.
if ($("#chatWindow").is(":visible")) {
payload = new Object();
payload.action="game_move";
payload.game_no=gamestarted;
payload.user_id=playerNames[pp];
payload.cardno=AIcardno;
socket.send(JSON.stringify(payload));
}
$("#oppo_card" + cc).css('background-image', "url(JerseyTeam" + playerNumbers[(pp == numberofplayers ? 1 : pp)] + ".gif)");
outStackturn();
endOfTurn();
}
Может быть, начать думать с точки зрения игрового цикла, что-то вроде этого:
- (хост) Трансляция состояния игры.
- (хост) Ожидает подтверждения от всех клиентов, что широковещание было получено.
- (клиенты) Визуализация состояния игры.
- (хост) Получает подтверждения, а затем сообщает следующему клиенту (и, следовательно, его игроку), что это его очередь.
- (хост) Ожидает ход игрока
- (клиент) Разблокирует пользовательский интерфейс, позволяющий игроку сделать ход.
- (игрок) заставляет двигаться.
- (клиент) Отправляет команду перемещения и повторно блокирует пользовательский интерфейс.
- (host) Получает команду перемещения и соответственно изменяет состояние игры.
Затем вернемся к 1.
Кроме того, думайте об игроках ИИ как об особом случае игроков-людей. Если вы можете сделать это правильно для людей, то (повторное) введение ИИ должно быть довольно простым.