xzfc / agar-expose

Yet another ogar client
12 stars 12 forks source link

Cell Control (Feature request) #6

Closed SJMakin closed 8 years ago

SJMakin commented 8 years ago

Really like this project.

Would be even better if the API exposed cell controls, such as move/split/shoot mass.

I have no idea if this is viable (or already possible!) but if it could be included in a future release I would be extremely grateful.

SJMakin commented 8 years ago

Looking at Main_Out.js it looks like it should just be a case of wrapping the registerEvent function for split/shoot. Not sure about moving though.

xzfc commented 8 years ago

You can split and shoot mass even without expose, by sending fake space and W key events. See minimal example for split:

window.onkeydown({
    keyCode: 32, // space
    target: document.getElementById("canvas"),
    preventDefault:() => undefined,
})

However, moving using sending mouse events to canvas is inconvenient: you have to translate move destination world coordinates to canvas pixel coordinates. So, most likely, I will add functions/hooks to control cell movement.

SJMakin commented 8 years ago

That would be most excellent. Thanks.

jakemayeux commented 8 years ago

I have succesfully used the $(window).mousemove() to control cell movement. To convert to canvas coordinates, all I did was add half the window dimensions so the origin of the mouse was in the center of the window. This works perfectly if you are only a single cell, however if you are split, I think the center may be a bit off. This method seems good enough at least until the movement hooks are added. I can try to find an example of the code if you are interested.

SJMakin commented 8 years ago

If you can provide a simple example of moving to the nearest cell or even '0,0', using the window.agar information, that would be splendid.

jakemayeux commented 8 years ago

Unfortunately agar is down right now and I don't currently have access to the original code so I am not entirely sure whether or not this will work. Either way this is essentially it

Using JQuery:

    function moveCell(x,y){
      $(window).trigger('mousemove', {
        clientX: x + $(window).width()/2,
        clientY: y + $(window).height()/2
      });
    }

Pure JS:

    function moveCell(x,y){
      window.onmousemove({
        clientX: x + window.innerWidth/2,
        clientY: y + window.innerHeight/2
      });
    }

moveCell(0, -10) = Up moveCell(10, 0) = Right

jakemayeux commented 8 years ago

Whoops, Agar is back up and I tested it. Turns out I needed to use canvas instead of window.

I'm going to have to mess around with this a bit more but for now it is in world coordinates so moveCell(0,0) brings you to the center of the map.

function moveCell(x,y){
  $('canvas').trigger('mousemove', {
    clientX: x + $('canvas').width()/2,
    clientY: y + $('canvas').height()/2
  });
}
jakemayeux commented 8 years ago

Try it again but change my function to

function moveCell(x,y){
  $('canvas').trigger('mousemove', {
    clientX: x,
    clientY: y
});
jakemayeux commented 8 years ago

Oh BTW, you can use the for-of loop instead of for-in. Its not necessary but I thought it was a pretty cool function when I found out about it. Plus it saves a line of code

for (var cell of window.agar.allCells) { var cell = window.agar.allCells[c];

xzfc commented 8 years ago

You can transtate coordinates using toPixelCoords function. I don't have access to PC right now, so it is untested.

var transform = {scale:1, x:0, y:0}
agar.hooks.beforeTransform = (ctx, t1x, t1y, s, t2x, t2y) => {
  transform = {scale:s, x:t2x*s + t1x, y:t2y*s + t1y}
}

function toWorldCoords(pixelCoords) {
  var x = (pixelCoords.x - transform.x) / transform.scale
  var y = (pixelCoords.y - transform.y) / transform.scale
  return {x, y}
}

function toPixelCoords(worldCoords) {
  var x = worldCoords.x*transform.scale + transform.x
  var x = worldCoords.y*transform.scale + transform.y
  return {x, y}
}
SJMakin commented 8 years ago

OK - I believe those conversion methods work a charm, but I am still not able to correctly move the players cell to the food. I added a method to draw a line between the player and and nearest food, and that looks great (when it displays - i should really use the drawing hooks I know) but the cell goes off in another direction entirely. I have tried both of the movement functions above and neither seems to work.

I tried for .. of but it didnt seem to work. Good to know about though :)

I am probably missing something silly. Any issues/questions please let me know.


// ==UserScript==
// @name        SJMBot
// @namespace   SJMBot
// @include     http://agar.io/*
// @include     https://agar.io/*
// @version     0.01
// @grant       none
// @author      SJMakin@Github
// ==/UserScript==

//Sample code
image = new Image();
image.crossOrigin = 'anonymous';
image.src = 'http://i.imgur.com/V8EOXwT.png';
window.agar.hooks.cellSkin = function(cell, old_skin) {
    if (old_skin) return old_skin;
    if (cell.isVirus) return image;
    return null;
}
console.log('Loaded Virus Image Switch');

//START - Helper methods

function computeDistance(x1, y1, x2, y2, s1, s2) {
        s1 = s1 || 0;
        s2 = s2 || 0;
        var xdis = x1 - x2; 
        var ydis = y1 - y2;
        var distance = Math.sqrt(xdis * xdis + ydis * ydis) - (s1 + s2);

        return distance;
}

function isMe(cell){
    for (var i = 0; i < window.agar.myCells.length; i++){            
        if (window.agar.myCells[i] == cell.id){
            return true;
        }           
    }
    return false;
}

var transform = {scale:1, x:0, y:0} 
window.agar.hooks.beforeTransform = (ctx, t1x, t1y, s, t2x, t2y) => { transform = {scale:s, x:t2x*s + t1x, y:t2y*s + t1y} } 

function toWorldCoords(pixelCoords) { 
    var x = (pixelCoords.x - transform.x) / transform.scale;
    var y = (pixelCoords.y - transform.y) / transform.scale;
    console.log('PC x: ' + pixelCoords.x + ' PC y: ' + pixelCoords.y + ' WC x ' + x + ' WC y ' + y)
    return [x, y] 
} 

function toPixelCoords(worldCoords) { 
    var x = worldCoords.x*transform.scale + transform.x; 
    var y = worldCoords.y*transform.scale + transform.y;
    console.log('WC x: ' + worldCoords.x + ' WC y: ' + worldCoords.y + ' PC x ' + x + ' PC y ' + y);
    return [x, y] 
}

function moveCell(x,y){
  $('canvas').trigger('mousemove', {
    clientX : x + $('canvas').width()/2,
    clientY : y + $('canvas').height()/2
  });
  console.log('Moving cell - x:' + x + ' y: ' + y);
}

function moveCell2(x,y){
  $('canvas').trigger('mousemove', {
    clientX: x,
    clientY: y
    });
  console.log('Moving cell 2 - x:' + x + ' y: ' + y);
}

function drawLine(startX, startY, endX, endY){
      var canvas = document.getElementById("canvas");
      var context = canvas.getContext('2d');

      context.beginPath();
      context.moveTo(startX, startY);
      context.lineTo(endX, endY);
      context.lineWidth = 4;
      context.stroke();

      console.log('Line drawn');
      return true;
}

//END - Helper methods 

//START - UI Customisation
window.agar.minScale = 0.5;
window.agar.drawGrid = false;
//END - UI Customisation

//START - Bot control

function processGameState(){
    //console.debug("SJMBot processGameState");
    var food = [];
    var virus = [];
    var me = [];
    var other = [];
    //console.dir(window.agar.allCells);
    for (var key in window.agar.allCells){
        var cell = window.agar.allCells[key];   
        //console.log(cell.id);
        if (isMe(cell)){
            me.push(cell);
        } else if (cell.size < 15) {
            food.push(cell);
        } else if (cell.isVirus){
            virus.push(cell);           
        } else {
            //Its not me, a virus or food, so it is another player
            other.push(cell);  
        }
    }
    //console.log(me.length);

    if (me.length > 0 && food.length > 0){
        var closest = 99999999;
        var target = {};
        for (var z = 0; z < food.length; z++){
            var dist = computeDistance(me[0].x, me[0].y, food[z].x, food[z].y);
            if (dist < closest){
                closest = dist;
                target = food[z];
            }
        }
        //console.dir(me);
        //console.dir(food);
        var position = toPixelCoords(target);
        moveCell(position[0], position[1]);
        var myPosition = toPixelCoords(me[0]);
        drawLine (myPosition[0], myPosition[1], position[0], position[1]);
    }

}
setInterval(processGameState, 30);
//END - Bot control
console.log("SJMBot loaded");
xzfc commented 8 years ago

Replacing moveCell with

function moveCell(x,y){
   document.getElementById('canvas').onmousemove({clientX:x, clientY:y})
}

works for me. I'm not into jQuery and can't say why $('canvas').trigger('mousemove', ... does not work.

SJMakin commented 8 years ago

Whey :+1: that works great! Thanks xzfc, you are a star!

SJMakin commented 8 years ago

Feel free to close this now, but it may still be worth considering adding a hook and/or documenting this for reference. Thanks again.