Seguir un color por la pantalla

Como están.
Mi duda en esta ocasión es un tema algo avanzado que supera totalmente mis pocos conocimientos de Delphi.
Les cuento que a mi me gusta hacer herramientas para editar juegos o para que la computadora juegue por nosotros.
En esta ocasión estoy tratando de hacer un BOT para un juego llamado PET Society de FaceBook, el cual es muy popular y a mi h¡Jita le fascina mucho.
El tema es que uno de los objetivos del juego es hacer click en un balón o pelota, según el país en donde se lo mire una vez que haya hecho contacto con la mascota del juego.
Mi pregunta para un experto es la siguiente:
Yo tengo un TWebBrowser y mediante un TTimer controlo los movimientos del personaje.
Quisiera saber si se puede hacer una rutina, función o procedimiento que me siga determinado tipo de color una vez que yo le digo cual es.
O sea, mi balón es de Color azul y yo le hago click más o menos en el X:=300 - Y :=500 de mi TWebBrowser.
Yo quisiera que a partir de ahí un TTimer me siguiera el color del balón y en el momento en que mi personaje me lo devuelve hacia X :¿=? - Y :=? (Por que no lo devuelve siempre al mismo lugar, sino que lo devuelve o más alto o más bajo) al pasar por ese Y :¿=? Mi aplicación lo detecte y envíe un click hasta ese lugar, para hacer contacto con el balón y seguir el objetivo del juego.
SI alguien lo suficientemente experimentado con Delphi podría ayudarme, me sería de gran utilidad para mi cometido, ya que hasta acá llegan casi mis conocimientos sobre Delphi por que nunca estudié para esto, si no, que lo hago solo por diversión.
Muchas gracias a tod@s.

1 Respuesta

Respuesta
1
Ante todo, debo decir que me parece bien que quieras hacer pasar un rato divertido a tu hija viendo como el ordenador juega solo. Pero no estoy de acuerdo en distribuir ese tipo de aplicaciones, pues cuando "ya la tiene todo el mundo", este tipo de aplicaciones "arruinan" el juego, ya que carece de sentido jugar a algo que cualquiera puede "adulterar".. (no creo que quieras "fusilar" el entretenimiento de tu hija).
En cuanto al tema de Delphi, creo que deberías plantear la solución de otra manera. Si la pelota estuviera siempre en un recuadro del tWebBrowser sería más fácil detectar su color (si la zona es más pequeña, es más rápido). Además, por lo que he podido entender, el clic hay que hacerlo en un momento determinado, así que intuyo que la pelota siempre pasa por un recuadro determinado (más alta o más baja). Lo que deberías hacer es, mediante un timer, capturar este recuadro (un rectángulo en vertical) y mantenerlo en una variable Bitmap, y en la siguiente ejecución del timer (250 milisegundos), vuelves a capturar el recuadro y lo comparas con el anterior. Si el recuadro cambia, la pelota está dentro del mismo. Es en ese momento cuando debes buscar su color para localizarla, pero solo en el recuadro, no en el tWebBrowser entero. Y por fin, lanzar el clic.
Para aportar un poco más al tema (del que ya conoces datos), aquí tienes un par de funciones que devuelven "verdadero" o "falso" al comparar dos bitmaps. En las 2 puedes elegir el "porcentaje de similitud". Es más preciso este porcentaje en la primera función, pues compara punto a punto, y la segunda lo hace línea a línea. Por la misma razón la segunda es mucho más rápida.
function SonIguales(Bitmap1, Bitmap2: TBitmap; Similitud: Integer): Boolean;
var X, Y, Aciertos: integer;
begin
  Result:= False;
  Aciertos := 0;
  for Y := 0 to Bitmap1.Height - 1 do
  for X := 0 to Bitmap1.Width - 1 do
  if Bitmap1.Canvas.Pixels[X,Y] = Bitmap2.Canvas.Pixels[X,Y] then inc(Aciertos);
  if (Aciertos * 100) div (Bitmap1.Width * Bitmap1.Height) < Similitud then exit;
  Result:= True;
end;
function SonIguales2(Bitmap1, Bitmap2: TBitmap; Similitud: Integer): Boolean;
var X, Y, Aciertos: integer;
begin
  Result:= False;
  if (Bitmap1.Width = Bitmap2.Width) and (Bitmap1.Height = Bitmap2.Height) and (Bitmap1.PixelFormat = Bitmap2.PixelFormat) then
  begin
    case Bitmap1.PixelFormat of
    pf32bit: X:= (Bitmap1.Width*4) -1;
    pf24bit: X:= (Bitmap1.Width*3) -1;
    pf16bit: X:= (Bitmap1.Width*2) -1;
    else X:= Bitmap1.Width -1;
  end;
  Aciertos := 0;
  for Y := 0 to Bitmap1.Height - 1 do
  if CompareMem(Bitmap1.ScanLine,Bitmap2.ScanLine,X) then inc(Aciertos);
  if (Aciertos * 100) div Bitmap1.Height < Similitud then exit;
  Result:= true;
end;
La forma de usarla seria la misma en ambos casos...
if SonIguales(MiBitmapUno, MiBitmapDos, 95) then
begin
 // Acciones si las imagenes alcanzan un 95% de similitud
end else
begin
 // Acciones si las imagenes NO alcanzan un 95% de similitud
end;
Hola, gracias por el código. Lo voy a probar ahora.
En cuanto a lo del juego, no es para que mi nena se quede mirando como el programa juega solo, si no para que en la noche cuando ella se va a dormir, lo deje jugando y de esta manera haga monedas para poder comprarle cosas a la mascota.
Bien, espero que te sea de utilidad. No olvides finalizar la pregunta.
Al añadir esta ultima respuesta, me he dado cuenta de que a la segunda función le falta un "end" al final de todo... o bien, puedes "compactar" los 2 métodos en una sola función:
function SonIguales(Bitmap1, Bitmap2: TBitmap; Similitud, Modo: Integer): Boolean;
var X, Y, Aciertos: Integer;
begin
  Result:= False;
  if (Bitmap1.Width = Bitmap2.Width) and (Bitmap1.Height = Bitmap2.Height) and (Bitmap1.PixelFormat = Bitmap2.PixelFormat) then
  begin
    Aciertos := 0;
    case Modo of
      1: begin
           for Y := 0 to Bitmap1.Height - 1 do
           for X := 0 to Bitmap1.Width - 1 do
           if Bitmap1.Canvas.Pixels[X,Y] = Bitmap2.Canvas.Pixels[X,Y] then inc(Aciertos);
           if (Aciertos * 100) div (Bitmap1.Width * Bitmap1.Height) >= Similitud then Result:= True;
         end;
      else begin
             case Bitmap1.PixelFormat of
               pf32bit: X:= (Bitmap1.Width*4) -1;
               pf24bit: X:= (Bitmap1.Width*3) -1;
               pf16bit: X:= (Bitmap1.Width*2) -1;
               else X:= Bitmap1.Width -1;
             end;
            for Y := 0 to Bitmap1.Height - 1 do
            if CompareMem(Bitmap1.ScanLine[Y],Bitmap2.ScanLine[Y],X) then inc(Aciertos);
            if (Aciertos * 100) div Bitmap1.Height >= Similitud then Result:= true;
           end;
    end;
  end;
end;
El último parámetro indicaría cual de los 2 métodos se utilizaría (1= por puntos, 2=por líneas), por ejemplo, para comparar por líneas:
if SonIguales(MiBitmapUno, MiBitmapDos, 95, 1) then 
begin 
 // Acciones si las imagenes alcanzan un 95% de similitud 
end else 
begin 
 // Acciones si las imagenes NO alcanzan un 95% de similitud 
end;

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas