Il s'agit d'un jeu de capture du drapeau, fortement inspiré et basé sur Red vs Blue - Pixel Team Battlebots . C'était une question géniale (merci beaucoup Calvin'sHobbies; j'espère que cela ne vous dérange pas que je vous ai volé sans vergogne beaucoup de code) - voici un autre roi basé sur l'équipe. Si tout va bien, capturer le drapeau exigera plus de coopération d'équipe aussi bien que plus de stratégie.
Pour mélanger, vous êtes considéré dans l'équipe rouge si le dernier chiffre de votre identifiant est compris entre 0
et 4
inclus. Cela devrait empêcher les mêmes équipes de se battre à nouveau, si les mêmes personnes décident de répondre. Le conseil est 350px
par 350px
. L'équipe bleue commence sur la moitié supérieure du plateau et l'équipe rouge commence sur la moitié inférieure.
La façon dont vous jouez capture le drapeau est la suivante: le but du jeu est de prendre le drapeau de l'équipe adverse et de le ramener de votre côté. Si vous êtes de leur côté, vous pouvez être tagué et envoyé en prison. Si vous êtes en prison, vous ne pouvez pas bouger. Si vous êtes de votre côté, votre travail consiste à étiqueter les membres de l'équipe adverse pour les envoyer en prison. La seule façon de sortir de prison est pour un membre de votre équipe qui est libre de taguer tout le monde en prison. (Notez que la prison est située du côté de l'équipe adverse).
Plus précisément:
- Il y a une constante -
FIELD_PADDING
- définie sur 20. Il s'agit du remplissage du champ. Si c'était zéro, les drapeaux et la prison seraient exactement aux coins de la toile. Comme ce n'est pas le cas, le drapeau et la prison sont à 20 pixels des coins. - Le drapeau bleu (rappelez-vous: l'équipe bleue est sur la moitié supérieure) est situé dans
(WIDTH - FIELD_PADDING, FIELD_PADDING) = (330, 20)
le coin supérieur droit par exemple. - Le drapeau rouge est à
(FIELD_PADDING, HEIGHT - FIELD_PADDING) = (20, 330)
- La prison bleue (où sont conservés les membres rouges) est à
(20, 20)
côté bleu, en haut à gauche. - La prison rouge, où sont détenus les membres bleus, est à
(330, 330)
Chaque membre de l'équipe commence au hasard à une position 45 < x < 305
et 45 < y < 175
pour le bleu et 175 < y < 305
pour le rouge. Aucun membre de l'équipe ne peut aller à moins de DEFENSE_RADIUS = 25
pixels de son propre drapeau ou de sa propre prison (sauf, bien sûr, si votre propre drapeau a été pris par un bot adverse, auquel cas vous devez étiqueter ce bot). C'est pour empêcher la garde des chiots comme les bots. Si vous allez dans cette plage, vous êtes "repoussé". De même, aucun membre de l'équipe ne peut sortir des limites (moins de zéro ou plus de 350) - si vous le faites, vous êtes repoussé à l'endroit légal le plus proche où vous pouvez être.
Chaque fois que vous déménagez, vous épuisez strength
. Votre strength
commence à 20
et est réapprovisionné à 2
chaque tour. La quantité de force que vous utilisez est égale à la distance que vous parcourez. Si votre force devenait négative en vous déplaçant vers un certain endroit, vous êtes empêché de faire ce mouvement. C'est probablement une bonne idée d'aller juste à grande vitesse 2
pour une poursuite normale. Vous ne devez utiliser des vitesses plus élevées que si vous êtes sur le point de gagner et avez besoin de la vitesse supplémentaire (à mon avis).
Spec :
La spécification est assez similaire à la question Pixel Team Battlebots. Vous devez écrire un bloc de code (rappelez-vous, pas de variables globales) en javascript. Il doit renvoyer un objet avec une valeur x
et une valeur y
représentant votre modification de x et vos modifications de y. La réponse suivante:
return {
x: 0,
y: -2
};
monte toujours jusqu'à ce qu'il heurte un mur. Vous ne pouvez pas modifier 8 heures après la publication (sauf pour LegionMammal98 qui pensait que le contrôleur ne chargeait pas son code et n'a pas testé) . Vous avez accès aux variables suivantes dans votre code:
this
- vous-même, en tant que joueur (voir ci-dessous ce que sont les joueurs)move
- le numéro du tour, commençant à 0tJailed
- un tableau de tous les joueurs de votre équipe qui sont emprisonnéseJailed
- un tableau de tous les joueurs de l'équipe adverse emprisonnésteam
- un tableau de tous les joueurs de votre équipe, PAS seulement ceux près de chez vousenemies
- un tableau de tous les joueurs de l'autre équipe, PAS seulement ceux près de chez voustFlag
- votre drapeau (vous essayez de le protéger)eFlag
- l'autre drapeau (vous essayez de le voler)messages
- expliqué ci-dessous- Une liste des constantes:
WIDTH = 350
,HEIGHT = 350
,FIELD_PADDING = 20
,DEFENSE_RADIUS = 25
.
Chaque "joueur" est un objet avec les propriétés suivantes:
x
ety
strength
id
isJailed
- vrai si le joueur est en prison
Chaque indicateur a les propriétés suivantes:
x
ety
pickedUpBy
- le joueur qui a actuellement le drapeau, ou nul si aucun joueur n'a le drapeau.
Maintenant, messages
c'est un objet qui est partagé entre vos coéquipiers. Je me fiche de ce que vous en faites. Le même objet est partagé et transmis à chacun des membres de votre équipe. C'est le seul moyen de communiquer. Vous pouvez y attacher des propriétés, partager des objets, etc. Il peut être aussi grand que vous le souhaitez - pas de limite de taille.
Chaque tour, les événements suivants se produisent:
- La liste des joueurs (rouges et bleus) est mélangée au hasard pour l'ordre des tours.
- Chaque joueur fait un pas.
- Si un membre de l'équipe rouge touche (à moins de 10 pixels de) des membres de l'équipe bleue du côté rouge, envoyez les membres de l'équipe bleue en prison, et vice versa. Un joueur emprisonné laisse tomber son drapeau et sa force tombe à zéro. Notez que la fonction step (code que vous fournissez) est toujours appelée - vous pouvez donc obtenir / définir des messages, mais vous ne pouvez pas vous déplacer en prison.
- Si un joueur touche (à moins de 10 pixels de) l'autre drapeau, alors l'autre drapeau est marqué comme "ramassé par" ce joueur. Lorsque le joueur bouge, le drapeau bouge - jusqu'à ce que le joueur soit tagué et qu'il soit emprisonné, c'est-à-dire.
- Si un joueur touche la prison de l'autre côté, libérez tout le monde dans cette prison. Lorsqu'un joueur est libéré de prison, il est téléporté à un endroit aléatoire de son côté.
Conseils:
- Au moins en capture régulière du drapeau, les attaques fonctionnent beaucoup mieux lorsque de nombreux joueurs partent en même temps, car cela a tendance à confondre les défenseurs quant au joueur à poursuivre.
- De même, les défenseurs pourraient vouloir coordonner qui ils chassent afin que les attaques ne passent pas
Extrait de pile:
window.onload=function(){(function(){function p(a,b,c,e){return Math.sqrt((a-c)*(a-c)+(b-e)*(b-e))}function l(a,b){this.x=this.y=0;this.id=a.id;this.title=a.title+" ["+this.id+"]";this.link=a.link||"javascript:;";this.team=b;this.isJailed=!1;this.flag=null;this.moveFn=new Function("move","tJailed","eJailed","team","enemies","tFlag","eFlag","messages","WIDTH","HEIGHT","FIELD_PADDING","DEFENSE_RADIUS",a.code);this.init()}function x(a,b){return Math.floor(Math.random()*(b-a))+a}function q(a,b){this.startX=this.x=a;this.startY=
this.y=b;this.following=null}function t(a,b){return a===e&&b||a===h&&!b?{x:20,y:20}:{x:g.width-20,y:g.height-20}}function y(){var a,b=$("#redTeam"),c=$("#blueTeam");for(a=0;a<e.length;++a)e[a].addToDiv(b);for(a=0;a<h.length;++a)h[a].addToDiv(c)}function z(){d.clearRect(0,0,g.width,g.height);d.beginPath();d.moveTo(0,g.height/2);d.lineTo(g.width,g.height/2);d.stroke();var a=e.concat(h),b,c;for(b=a.length-1;0<b;b--){c=Math.floor(Math.random()*(b+1));var f=a[b];a[b]=a[c];a[c]=f}for(b=0;b<a.length;++b)a[b].step(u);
for(b=0;b<e.length;++b)for(c=0;c<h.length;++c)10>p(e[b].x,e[b].y,h[c].x,h[c].y)&&(e[b].y<g.height/2&&e[b].goToJail(),h[c].y>g.height/2&&h[c].goToJail());for(b=0;b<a.length;++b)c=a[b].team===e!==!0?m:n,!c.following&&10>p(a[b].x,a[b].y,c.x,c.y)&&(c.following=a[b]);for(b=0;b<a.length;++b)if(c=t(a[b].team,!0),!a[b].isJailed&&10>p(a[b].x,a[b].y,c.x,c.y))for(c=a[b].team,f=0;f<c.length;++f)c[f].isJailed&&(c[f].isJailed=!1,c[f].init());m.follow();n.follow();b=m.y<g.height/2;c=n.y>g.height/2;b&&c&&alert("EXACT TIE!!!! This is very unlikely to happen.");
b&&!c&&(alert("Blue wins!"),$("#playpause").click().hide());c&&!b&&(alert("Red wins!"),$("#playpause").click().hide());for(b=0;b<a.length;++b)a[b].draw(d);m.draw("red");n.draw("blue");u++}$.ajaxSetup({cache:!1});var e=[],h=[],g=$("canvas")[0],d=g.getContext("2d"),v,u=0,m={},n={},r=!0,A={},B={},w;l.prototype.init=function(){this.x=x(45,g.width-45);this.y=x(45,g.height/2);this.team===e&&(this.y+=g.height/2);this.strength=20};l.prototype.makeShallowCopy=function(){return{x:this.x,y:this.y,strength:this.strength,
id:this.id,isJailed:this.isJailed}};l.prototype.goToJail=function(){this.isJailed=!0;var a=this.team===e!==!0?m:n;(this.team===e!==!0?m:n).following===this&&(a.following=null);a=t(this.team,!0);this.x=a.x;this.y=a.y;this.strength=0};l.prototype.step=function(a){function b(a,b,c){var e,d,f;for(e=0;e<a.length;++e)d=a[e],d!==C&&(f=d.makeShallowCopy(),d.isJailed?b.push(f):c.push(f))}var c=[],f=[],d=[],k=[],l=this.team===e?h:e,C=this,q=this.team===e?m:n,r=this.team===e?n:m;b(this.team,c,d);b(l,f,k);f=
this.moveFn.call(this.makeShallowCopy(),a,c,f,d,k,q.copy(),r.copy(),this.team===e?A:B,g.width,g.height,20,25);"object"===typeof f&&"number"===typeof f.x&&"number"===typeof f.y&&(d=p(0,0,f.x,f.y),a=t(this.team,!1),c=this.team===e!==!1?m:n,d<=this.strength&&(this.strength-=d,this.x+=f.x,this.y+=f.y,0>this.x&&(this.x=0),0>this.y&&(this.y=0),this.x>g.width&&(this.x=g.width),this.y>g.height&&(this.y=g.height),f=p(this.x,this.y,c.x,c.y),d=p(this.x,this.y,a.x,a.y),25>f&&null===c.following&&(this.x=25*(this.x-
c.x)/f*1.3+c.x,this.y=25*(this.y-c.y)/f*1.3+c.y),25>d&&(this.x=25*(this.x-a.x)/d*1.3+a.x,this.y=25*(this.y-a.y)/d*1.3+a.y)),this.isJailed||(this.strength+=2),20<this.strength&&(this.strength=20))};l.prototype.addToDiv=function(a){var b=$("<option>").text(this.title).val(this.id);a.find(".playersContainer").append(b)};l.prototype.draw=function(a){a.fillStyle=this.team===e?"red":"blue";a.beginPath();a.arc(this.x,this.y,5,0,2*Math.PI,!0);a.fill();!this.isJailed&&$("#labels").is(":checked")&&a.fillText(this.title,
this.x+5,this.y+10)};q.prototype.draw=function(a){d.strokeStyle=a;d.beginPath();d.arc(this.x,this.y,5,0,2*Math.PI,!0);d.stroke();d.fillStyle=a;d.strokeRect(this.x-2,this.y-2,4,2);d.beginPath();d.moveTo(this.x-2,this.y);d.lineTo(this.x-2,this.y+3);d.stroke()};q.prototype.copy=function(){return{x:this.x,y:this.y,pickedUpBy:this.following&&this.following.makeShallowCopy()}};q.prototype.follow=function(){null!==this.following&&(this.x=this.following.x,this.y=this.following.y)};$("#newgame").click(function(){function a(a,
b){w?b(w):$.get("https://api.stackexchange.com/2.2/questions/"+(49028).toString()+"/answers",{page:a.toString(),pagesize:100,order:"asc",sort:"creation",site:"codegolf",filter:"!JDuPcYJfXobC6I9Y-*EgYWAe3jP_HxmEee"},b,"json")}function b(g){w=g;g.items.forEach(function(a){function b(a){return $("<textarea>").html(a).text()}var d=4>=a.owner.user_id%10?e:h;a.owner.display_name=b(a.owner.display_name);if(!(a.hasOwnProperty("last_edit_date")&&28800<a.last_edit_date-a.creation_date&&33208!==a.owner.user_id||
-1<p.indexOf(a.owner.user_id))){p.push(a.owner.user_id);var g=c.exec(a.body);if(!(null===g||1>=g.length)){var f={};f.id=a.owner.user_id;f.title=a.owner.display_name;f.code=b(g[1]);f.link=a.link;d.push(new l(f,d))}}});g.has_more?a(++d,b):(console.log("Red team",e),console.log("Blue team",h),y(),clearInterval(v),r=!0,$("#playpause").show().click())}var c=/<pre><code>((?:\n|.)*?)\n<\/code><\/pre>/,d=1,p=[];e=[];h=[];u=0;m=new q(20,g.height-20);n=new q(g.width-20,20);$(".teamColumn select").empty();var k=
$("#testbotCode").val();0<k.length&&(console.log("Using test entry"),k={title:"TEST ENTRY",link:"javascript:;",code:k},$("#testbotIsRed").is(":checked")&&(k.id=-1,e.push(new l(k,e)),k.id=-3,e.push(new l(k,e))),$("#testbotIsBlue").is(":checked")&&(k.id=-2,h.push(new l(k,h)),k.id=-4,h.push(new l(k,h))));a(1,b)});$("#playpause").hide().click(function(){r?(v=setInterval(z,25),$(this).text("Pause")):(clearInterval(v),$(this).text("Play"));r=!r})})();}
#main{padding:10px;text-align:center}#testbot{padding:10px;clear:both}.teamColumn{width:25%;padding:0 10px;border:3px solid;border-color:#000;text-align:center;height:500px;overflow:scroll;white-space:nowrap}.playersContainer p{padding:0;margin:0}#redTeam{float:left;border-color:red;color:red;background-color:#fee}#blueTeam{float:right;border-color:#00f;color:#00f;background-color:#fee}#arena{display:inline-block;width:40%;text-align:center}canvas{border:1px solid #000}select{width:100%}
<script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script><div id=main><div class=teamColumn id=redTeam><h1>Red Team</h1><select size=20 class=playersContainer></select></div><div id=arena><h1>Battlefield</h1><canvas width=350 height=350></canvas></div><div class=teamColumn id=blueTeam><h1>Blue Team</h1><select size=20 class=playersContainer></select></div><div id=loadingInfo><button id=newgame>New Game</button> <button id=playpause>Play</button><br><input type=checkbox id="labels"> Show labels</div></div><div id=testbot><textarea id=testbotCode placeholder="testbot code"></textarea><br><input type=checkbox id="testbotIsRed">Red Team<br><input type=checkbox id="testbotIsBlue">Blue Team<br></div>
Contrôleur: http://jsfiddle.net/prankol57/4L7fdmkk/
Contrôleur plein écran: http://jsfiddle.net/prankol57/4L7fdmkk/embedded/result/
Faites-moi savoir s'il y a des bogues dans le contrôleur.
Remarque: Si vous allez sur le contrôleur et pensez qu'il ne charge rien, appuyez sur "Nouveau jeu". Il ne charge tout après avoir appuyé sur "Nouveau jeu" afin qu'il puisse charger tous les bots et les bots de test possibles à la fois.
Bonne chance.
Si quelqu'un veut voir un exemple de jeu, j'ai créé un exemple de bot que vous pouvez copier et coller dans la zone de texte "testbot" (le testbot crée deux doublons sur chaque équipe; vérifiez à la fois l'équipe rouge et l'équipe bleue):
var r2 = Math.sqrt(2);
if (this.id === -1) {
// red team 1
// go after flag regardless of what is going on
if (eFlag.pickedUpBy !== null && eFlag.pickedUpBy.id === this.id) {
return {
x: 0,
y: 2
};
}
return {
x: this.x < eFlag.x ? r2 : -r2,
y: this.y < eFlag.y ? r2 : -r2
};
}
if (this.id === -2) {
// blue team 1
// a) go after opposing team members on your side b) get the other flag if no enemies on your side
var closestEnemy = null;
for (var i = 0; i < enemies.length; ++i) {
if (enemies[i].y < HEIGHT/2 && (closestEnemy === null || enemies[i].y < closestEnemy.y)) {
closestEnemy = enemies[i];
}
}
if (closestEnemy !== null) {
return {
x: this.x < closestEnemy.x ? r2 : -r2,
y: this.y < closestEnemy.y ? r2 : -r2
};
}
if (eFlag.pickedUpBy !== null && eFlag.pickedUpBy.id === this.id) {
return {
x: 0,
y: -2
};
}
return {
x: this.x < eFlag.x ? r2 : -r2,
y: this.y < eFlag.y ? r2 : -r2
};
}
if (this.id === -3) {
// red team 2
// a) defend the flag b) if at least half of enemies in jail and no enemies on this side, free jailed reds and quickly return
var closestEnemy = null;
for (var i = 0; i < enemies.length; ++i) {
if (enemies[i].y > HEIGHT/2 && (closestEnemy === null || enemies[i].y > closestEnemy.y)) {
closestEnemy = enemies[i];
}
}
if (closestEnemy !== null) {
return {
x: this.x < closestEnemy.x ? r2 : -r2,
y: this.y < closestEnemy.y ? r2 : -r2
};
}
if (enemies.length / eJailed.length <= 1 && tJailed.length > 0) {
return {
x: this.x < FIELD_PADDING ? r2 : -r2,
y: this.y < FIELD_PADDING ? r2 : -r2
};
}
if (this.y < 350/2) return {x: 0, y: 2};
return {
x: this.x < tFlag.x ? r2 : -r2,
y: this.y < tFlag.y ? r2 : -r2
};
}
if (this.id === -4) {
// blue team 2
// a) try freeing jail if there are jailed team members b) capture the flag
if (tJailed.length > 0) {
return {
x: this.x < WIDTH - FIELD_PADDING ? r2 : -r2,
y: this.y < HEIGHT - FIELD_PADDING ? r2 : -r2
};
}
if (eFlag.pickedUpBy !== null && eFlag.pickedUpBy.id === this.id) {
return {
x: 0,
y: -2
};
}
return {
x: this.x < eFlag.x ? r2 : -r2,
y: this.y < eFlag.y ? r2 : -r2
};
}