이 게임은 Red vs. Blue-Pixel Team Battlebots 에서 크게 영감을 얻은 깃발을 사로 잡는 게임입니다 . 정말 멋진 질문이었습니다 (캘빈의 취미에 감사합니다. 부끄럽게도 많은 코드를 훔쳤다는 것을 신경 쓰지 않기를 바랍니다) – 여기 또 다른 팀 기반의 왕이 있습니다. 바라건대 깃발을 잡으려면 더 많은 팀 협력과 더 많은 전략이 필요합니다.
그것을 섞기 위해, 당신은 당신의 ID의 마지막 숫자가 그 사이 0
에 4
포함 되면 빨간색 팀으로 간주됩니다 . 이것은 같은 사람들이 대답하기로 결정한 경우 정확히 같은 팀이 다시 싸우는 것을 막아야합니다. 보드는 350px
입니다 350px
. 파란색 팀은 보드의 위쪽 절반에서 시작하고 빨간색 팀은 아래쪽 절반에서 시작합니다.
깃발을 잡는 방법은 다음과 같습니다. 게임의 목적은 상대 팀의 깃발을 가져와 자신의 편으로 가져 오는 것입니다. 당신이 그들의 편에 있다면, 당신은 꼬리표를 붙여 감옥에 보내질 수 있습니다. 당신이 감옥에 있다면, 당신은 움직일 수 없습니다. 당신이 편에 있다면, 당신의 임무는 상대 팀원을 태그하여 감옥에 보내도록하는 것입니다. 감옥에서 나가는 유일한 방법은 감옥에있는 모든 사람을 자유롭게 태그 할 수있는 팀원을위한 것입니다. (감옥은 상대 팀 측에 있습니다).
구체적으로 특별히:
- 상수
FIELD_PADDING
는--20으로 설정됩니다. 이것은 필드의 패딩입니다. 그것이 0이라면, 깃발과 감옥은 정확히 캔버스의 모서리에있을 것입니다. 그렇지 않으므로 플래그와 감옥은 모서리에서 20 픽셀 떨어져 있습니다. - 파란색 깃발 (상단 : 파란색 팀은 상단에 있음)은
(WIDTH - FIELD_PADDING, FIELD_PADDING) = (330, 20)
오른쪽 상단에 있습니다. - 붉은 깃발은
(FIELD_PADDING, HEIGHT - FIELD_PADDING) = (20, 330)
- 파란색 교도소 (빨간색 멤버가 보관되어있는 곳)는
(20, 20)
왼쪽, 즉 왼쪽 상단에 있습니다. - 파란색 회원이 유지되는 붉은 감옥은
(330, 330)
모든 팀 구성원은 무작위 위치에서 시작 45 < x < 305
하고 45 < y < 175
파란색과 175 < y < 305
빨간색을 위해. 팀원 DEFENSE_RADIUS = 25
은 자신의 깃발이나 자신의 감옥의 픽셀 안에 들어갈 수 없습니다 (물론 상대방 깃발이 자신의 깃발을 가져간 경우가 아니라면 해당 로봇에 태그를 추가해야합니다). 이것은 봇과 같은 강아지 보호를 방지하기위한 것입니다. 당신이 그 범위 안에 들어가면, 당신은 "푸시"됩니다. 마찬가지로, 어떤 팀 구성원도 범위를 벗어날 수 없습니다 (0보다 적거나 350을 초과). 그렇게하면 가장 가까운 법적 장소로 밀려납니다.
움직일 때마다 up을 사용합니다 strength
. 당신의 strength
시작 20
은 2
매 턴마다 보충됩니다 . 사용하는 힘의 양은 이동 거리와 같습니다. 특정 장소로 이사하여 힘이 부정적으로 느껴지면 그 장소로 이동할 수 없습니다. 2
정상적인 추격을 위해 속도 를 맞추는 것이 좋습니다 . 승리에 가까워지고 추가 속도가 필요한 경우에만 더 높은 속도를 사용해야합니다 (제 의견으로는).
사양 :
이 사양은 Pixel Team Battlebots 질문과 매우 유사합니다. 자바 스크립트로 코드 블록을 작성해야합니다 (글로벌 변수 없음). x의 변화와 y의 변화를 나타내는 x
-value와 y
-value를 가진 객체를 반환해야 합니다. 다음 답변 :
return {
x: 0,
y: -2
};
벽에 부딪 칠 때까지 항상 위로 움직입니다. 게시 후 8 시간 동안 편집 할 수 없습니다 (컨트롤러가 코드를로드하지 않고 테스트하지 않았다고 생각한 LegionMammal98 제외) . 코드에서 다음 변수에 액세스 할 수 있습니다.
this
-플레이어로서 자신 (플레이어가 무엇인지 아래 참조)move
-0부터 시작하는 둥근 숫자tJailed
-팀에 투옥 된 모든 플레이어의 배열eJailed
-상대 팀에 투옥 된 모든 플레이어의 배열team
-가까운 플레이어 만이 아닌 팀의 모든 플레이어 배열enemies
-가까운 팀원이 아닌 다른 팀의 모든 선수 배열tFlag
-당신의 깃발 (당신은 그것을 보호하려고합니다)eFlag
-다른 깃발 (당신이 그것을 훔치려 고합니다)messages
-아래 설명- 상수의 목록 :
WIDTH = 350
,HEIGHT = 350
,FIELD_PADDING = 20
,DEFENSE_RADIUS = 25
.
모든 "플레이어"는 다음과 같은 속성을 가진 객체입니다.
x
과y
strength
id
isJailed
-플레이어가 감옥에있는 경우 true
모든 플래그에는 다음과 같은 속성이 있습니다.
x
과y
pickedUpBy
-현재 깃발을 가지고있는 플레이어. 깃발이없는 플레이어는 null
이제는 messages
팀원간에 공유되는 개체입니다. 나는 당신이 무엇을하는지 상관하지 않습니다. 동일한 개체가 공유되어 모든 팀 구성원에게 전달됩니다. 이것이 당신이 의사 소통 할 수있는 유일한 방법입니다. 속성을 첨부하거나 객체를 공유 할 수 있습니다. 크기 제한없이 원하는만큼 클 수 있습니다.
매번 다음과 같은 일이 발생합니다.
- 플레이어 목록 (빨강과 파랑 모두)은 순서대로 무작위로 섞입니다.
- 모든 플레이어가 움직입니다.
- 빨간색 팀 구성원이 빨간색 측면의 파란색 팀 구성원을 만지면 (10 픽셀 이내) 파란색 팀 구성원을 감옥에 보내고 그 반대도 마찬가지입니다. 투옥 된 플레이어는 깃발을 떨어 뜨리고 힘은 0으로 떨어집니다. 스텝 기능 (제공 한 코드)은 여전히 호출되므로 메시지를 가져 오거나 설정할 수 있지만 감옥에있는 동안에는 이동할 수 없습니다.
- 어떤 플레이어가 다른 깃발을 건 드리면 (10 픽셀 이내), 다른 깃발은 그 플레이어가 "픽업 한"것으로 표시됩니다. 플레이어가 움직일 때, 깃발은 플레이어가 태깅되어 감옥에 갈 때까지 움직입니다.
- 어떤 플레이어가 상대방의 감옥에 닿으면 그 감옥에있는 모든 사람을 해방하십시오. 플레이어가 감옥에서 풀려 나면 상대방의 임의 위치로 순간 이동됩니다.
힌트 :
- 적어도 정기적으로 깃발을 잡으면, 많은 플레이어가 한 번에 갈 때 공격이 훨씬 잘 작동합니다. 수비수는 어떤 플레이어를 쫓아 야하는지 혼란스럽게 만듭니다.
- 마찬가지로, 수비수는 쫓고있는 사람을 조율하여 공격이 진행되지 않도록 할 수 있습니다.
스택 스 니펫 :
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>
컨트롤러 : http://jsfiddle.net/prankol57/4L7fdmkk/
전체 화면 컨트롤러 : http://jsfiddle.net/prankol57/4L7fdmkk/embedded/result/
컨트롤러에 버그가 있는지 알려주세요.
참고 : 컨트롤러로 가서 아무것도로드하지 않는다고 생각되면 "새 게임"을 누르십시오. "새 게임"을 누른 후에 만 모든 봇을로드하고 모든 봇과 가능한 테스트 봇을 한 번에로드 할 수 있습니다.
행운을 빕니다.
누구나 예제 게임을보고 싶은 경우, "testbot"텍스트 영역에 복사하여 붙여 넣을 수있는 예제 봇을 만들었습니다 (테스트 봇은 각 팀마다 두 개의 복제본을 생성합니다.
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
};
}