I have made some very simple bots for some web based games and I wanted to move on to other games which require to use some more advanced features.
I have used pyautogui to bot in web based games and it has been easy because all the images are static (not moving) but when I want to click something in a game what is moving, it could be a Character or a Creature running around pyautogui is not really efficient because it looks for pixels/colors that are exactly the same.
Please suggest any references or any libraries or functions that can detect a model or character even though the character is moving?
Here is an example of something I'd like to click on:
Moving creature Gif image
Thanks.
I noticed the image you linked to is a gif of a mob from world of warcraft.
As a hobby I have been designing bots for MMO's on and off over the past few years.
There are no specific python libraries that will allow you to do what you're asking that I'm aware of; however, taking WoW as an example...
If you are using Windows as your OS in question you will be using Windows API calls to get manipulate your game's target process (here wow.exe).
There are two primary approaches to this:
1) Out of process - you do everything via reading memory values from known offsets and respond by using the Windows API to simulate mouse and/or keyboard input (your choice).
1a) I will quickly mention that although for most modern games it is not an option (due to built-in anti-cheating code), you can also manipulate the game by writing directly to memory. In WAR (warhammer online) when it was still live, I made a grind bot that wrote to memory whenever possible, as they had not enabled punkbuster to protect the game from this. WoW is protected by the infamous "Warden."
2) DLL Injection - WoW has a built-in API created in LUA. As a result, over the years, many hobbyist programmers and hackers have taken apart the binary to reveal its inner workings. You might check out the Memory Editing Forum on ownedcore.com if you are wanting to work with WoW. Many have shared the known offsets in the binary where one can hook into LUA functions and as a result perform in-game actions directly and also tap into needed information. Some have even shared their own DLL's
You specifically mentioned clicking in-game 3d objects. I will close by sharing with you a snippet shared on ownedcore that allows one to do just this. This example encompasses use of both memory offsets and in-game function calls:
using System;
using SlimDX;
namespace VanillaMagic
{
public static class Camera
{
internal static IntPtr BaseAddress
{
get
{
var ptr = WoW.hook.Memory.Read<IntPtr>(Offsets.Camera.CameraPtr, true);
return WoW.hook.Memory.Read<IntPtr>(ptr + Offsets.Camera.CameraPtrOffset);
}
}
private static Offsets.CGCamera cam => WoW.hook.Memory.Read<Offsets.CGCamera>(BaseAddress);
public static float X => cam.Position.X;
public static float Y => cam.Position.Y;
public static float Z => cam.Position.Z;
public static float FOV => cam.FieldOfView;
public static float NearClip => cam.NearClip;
public static float FarClip => cam.FarClip;
public static float Aspect => cam.Aspect;
private static Matrix Matrix
{
get
{
var bCamera = WoW.hook.Memory.ReadBytes(BaseAddress + Offsets.Camera.CameraMatrix, 36);
var m = new Matrix();
m[0, 0] = BitConverter.ToSingle(bCamera, 0);
m[0, 1] = BitConverter.ToSingle(bCamera, 4);
m[0, 2] = BitConverter.ToSingle(bCamera, 8);
m[1, 0] = BitConverter.ToSingle(bCamera, 12);
m[1, 1] = BitConverter.ToSingle(bCamera, 16);
m[1, 2] = BitConverter.ToSingle(bCamera, 20);
m[2, 0] = BitConverter.ToSingle(bCamera, 24);
m[2, 1] = BitConverter.ToSingle(bCamera, 28);
m[2, 2] = BitConverter.ToSingle(bCamera, 32);
return m;
}
}
public static Vector2 WorldToScreen(float x, float y, float z)
{
var Projection = Matrix.PerspectiveFovRH(FOV * 0.5f, Aspect, NearClip, FarClip);
var eye = new Vector3(X, Y, Z);
var lookAt = new Vector3(X + Matrix[0, 0], Y + Matrix[0, 1], Z + Matrix[0, 2]);
var up = new Vector3(0f, 0f, 1f);
var View = Matrix.LookAtRH(eye, lookAt, up);
var World = Matrix.Identity;
var WorldPosition = new Vector3(x, y, z);
var ScreenPosition = Vector3.Project(WorldPosition, 0f, 0f, WindowHelper.WindowWidth, WindowHelper.WindowHeight, NearClip, FarClip, World*View*Projection);
return new Vector2(ScreenPosition.X, ScreenPosition.Y-20f);
If the mobs colors are somewhat easy to differentiate from the background you can use pyautogui pixel matching.
import pyautogui
screen = pyautogui.screenshot()
# Use this to scan the area of the screen where the mob appears.
(R, G, B) = screen.getpixel((x, y))
# Compare to mob color
If colors vary you can use color tolerance:
pyautogui.pixelMatchesColor(x, y, (R, G, B), tolerance=5)
Related
I'm currently writing a Processing sketch that needs to access multiple audio inputs, but Processing only allows access to the default line in. I have tried getting Lines straight from the Java Mixer (accessed within Processing), but I still only get the signal from whichever line is currently set to default on my machine.
I've started looking at sending the sound via OSC from SuperCollider, as recommended here. However, since I'm very new to SuperCollider and their documentation and support is more focused on generating sound than on accessing inputs, my next step will probably be to play around with Beads and Jack, as suggested here.
Does anyone have (1) other suggestions, or (2) concrete examples of getting multiple inputs from either SuperCollider or Beads/Jack to Processing?
Thank you in advance!
Edit: The sound will be used to power custom music visualizations (think the iTunes visualizer, but much more song specific). We have this working with multiple mp3s; now what I need is to able to get a float[] buffer from each mic. Hoping to have 9 different mics, though we'll settle for 4 if that is more doable.
For hardware, at this point, we are just using mics and XLR to USB cables. (Have considered a pre-amp, but so far this has been sufficient.) I am currently on Windows, but I think that we will ultimately switch to a Mac.
Here was my attempt with just Beads (it works fine for the laptop, since I do that one first, but the headset buffer has all 0's; if I switch them and put the headset first, the headset buffer will be correct, but the laptop will contain all 0's):
void setup() {
size(512, 400);
JavaSoundAudioIO headsetAudioIO = new JavaSoundAudioIO();
JavaSoundAudioIO laptopAudioIO = new JavaSoundAudioIO();
headsetAudioIO.selectMixer(5);
headsetAudioCon = new AudioContext(headsetAudioIO);
laptopAudioIO.selectMixer(4);
laptopAudioCon = new AudioContext(laptopAudioIO);
headsetMic = headsetAudioCon.getAudioInput();
laptopMic = headsetAudioCon.getAudioInput();
} // setup()
void draw() {
background(100,0, 75);
laptopMic.start();
laptopMic.calculateBuffer();
laptopBuffer = laptopMic.getOutBuffer(0);
for (int j = 0; j < laptopBuffer.length - 1; j++)
{
println("laptop; " + j + ": " + laptopBuffer[j]);
line(j, 200+laptopBuffer[j]*50, j+1, 200+laptopBuffer[j+1]*50);
}
laptopMic.kill();
headsetMic.start();
headsetMic.calculateBuffer();
headsetBuffer = headsetMic.getOutBuffer(0);
for (int j = 0; j < headsetBuffer.length - 1; j++)
{
println("headset; " + j + ": " + headsetBuffer[j]);
line(j, 50+headsetBuffer[j]*50, j+1, 50+headsetBuffer[j+1]*50);
}
headsetMic.kill();
} // draw()
My attempt at adding Jack contains this line:
ac = new AudioContext(new AudioServerIO.Jack(), 44100, new IOAudioFormat(44100, 16, 4, 4));
but I get the error:
Jun 22, 2016 9:17:24 PM org.jaudiolibs.beads.AudioServerIO$1 run
SEVERE: null
org.jaudiolibs.jnajack.JackException: Can't find native library
at org.jaudiolibs.jnajack.Jack.getInstance(Jack.java:428)
at org.jaudiolibs.audioservers.jack.JackAudioServer.initialise(JackAudioServer.java:102)
at org.jaudiolibs.audioservers.jack.JackAudioServer.run(JackAudioServer.java:86)
at org.jaudiolibs.beads.AudioServerIO$1.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.UnsatisfiedLinkError: Unable to load library 'jack': Native library (win32-x86-64/jack.dll) not found in resource path ([file:/C:/Users/...etc...)
And when I'm in Jack, I don't see my mic (which seems like a huge red flag to me, though I am completely new to Jack). Should this AudioContext show up as an Input in Jack? Or vice versa -- find my mic there first and then get it from Jack to Processing?
(Forgive my inexperience, and thank you again! My lack of knowledge in Jack makes me wonder if I should revisit SuperCollider instead...)
I had the same issue a few years ago and I used a combination of JACK, JNAJack and Beads. You can follow this Beads Google Group thread for more details.
At the that time I had to use this version of Beads (2012-04-23), but I hope those changes probably made it into the main project by now.
For reference, here is the basic class I used:
import java.util.Arrays;
import org.jaudiolibs.beads.AudioServerIO;
import net.beadsproject.beads.analysis.featureextractors.FFT;
import net.beadsproject.beads.analysis.featureextractors.PowerSpectrum;
import net.beadsproject.beads.analysis.segmenters.ShortFrameSegmenter;
import net.beadsproject.beads.core.AudioContext;
import net.beadsproject.beads.core.AudioIO;
import net.beadsproject.beads.core.UGen;
import net.beadsproject.beads.ugens.Gain;
import processing.core.PApplet;
public class BeadsJNA extends PApplet {
AudioContext ac;
ShortFrameSegmenter sfs;
PowerSpectrum ps;
public void setup(){
//defining audio context with 6 inputs and 6 outputs - adjust this based on your sound card / JACK setup
ac = new AudioContext(new AudioServerIO.Jack(),512,AudioContext.defaultAudioFormat(6,6));
//getting 4 audio inputs (channels 1,2,3,4)
UGen microphoneIn = ac.getAudioInput(new int[]{1,2,3,4});
Gain g = new Gain(ac, 1, 0.5f);
g.addInput(microphoneIn);
ac.out.addInput(g);
println("no. of inputs: " + ac.getAudioInput().getOuts());
//test get some FFT power spectrum data form the
sfs = new ShortFrameSegmenter(ac);
sfs.addInput(ac.out);
FFT fft = new FFT();
sfs.addListener(fft);
ps = new PowerSpectrum();
fft.addListener(ps);
ac.out.addDependent(sfs);
ac.start();
}
public void draw(){
background(255);
float[] features = ps.getFeatures();
if(features != null){
for(int x = 0; x < width; x++){
int featureIndex = (x * features.length) / width;
int barHeight = Math.min((int)(features[featureIndex] *
height), height - 1);
line(x, height, x, height - barHeight);
}
}
}
public static void main(String[] args) {
PApplet.main(BeadsJNA.class.getSimpleName());
}
}
My problem is getting the pixels in a window. I can't find a way to do this. I using standard windows functions and Direct2D (not DirectDraw).
I am using standard initialization of new window:
WNDCLASS wc;
wc.style = CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(6);
wc.lpszMenuName = 0;
wc.lpszClassName = L"WINDOW"; RegisterClass(&wc);
hWnd = CreateWindow(L"WINDOW", L"Game", WS_OVERLAPPEDWINDOW,100,100,1024,768,NULL,NULL,hInstance,NULL);
Then I create a D2D1factory object and draw the bitmap in the window:
HWND hWnd = NULL;
srand((unsigned int)time((time_t)NULL));
ID2D1Factory* factory = NULL;
ID2D1HwndRenderTarget* rt = NULL;
CoInitializeEx(NULL,COINIT_MULTITHREADED);
My_CreateWindow(&hWnd, hInstance);
My_CreateFactory(&hWnd, factory, rt);
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,&factory);
factory->CreateHwndRenderTarget(RenderTargetProperties(), HwndRenderTargetProperties(hWnd,SizeU(800,600)), &rt);
// tons of code
rt->BeginDraw(); rt->DrawBitmap(background[0], RectF(0,0,800,600));
rt->DrawBitmap(GIFHorse[(int)iterator],
RectF(0+MyX-100,0+MyY-100,100+MyX,100+MyY));
rt->DrawBitmap(Star[(int)iterator], RectF(0 + starX, 0 + starY, 50 + starX, 50+starY)); rt->EndDraw();
I need to calculate the hits (I am trying to make simple game). So that's why I need access to all pixels in window.
I'm thinking about using other algorithms, but they're harder to make and I want to start with something easier.
I know about the GetPixel() function, but I cant understand what I should use for HDC.
There is no simple and easy way to get to D2D pixels.
A simple collision detection can be implemented using geometries. If you have outlines of your objects in ID2D1Geometry objects you can compare them using ID2D1Geometry::CompareWithGeometry.
If you insist on the pixels, a way to access them is from the DC obtainable via IDXGISurface1::GetDC
In this case you need to use the DXGI surface render target and the swap chain instead of the hwnd render target.
Step by step:
D3D11CreateDeviceAndSwapChain gives you the swap chain.
IDXGISwapChain::GetBuffer gives you the DXGI surface.
ID2D1Factory::CreateDxgiSurfaceRenderTarget gives you the render target.
IDXGISurface1::GetDC gives you the DC. Read the remarks on this page!
I would like to generate random/noise points along each character of a multiple line text. I've tried this with the Geomerative library, but unfortunately it does not support multi line. Any other solution?
You could find a library to get the path points of the text or if simply adding points, you could get a 2D snapshot(either using get() or PGraphics) of the text and fill in pixels. Here's a minimal example.
PImage snapshot;
int randomSize = 3;
void setup(){
//render some text
background(255);
fill(0);
textSize(40);
text("Hello",0,50);
//grab a snapshot
snapshot = get();
}
void draw(){
int rx = (int)random(snapshot.width);//pick a random pixel location
int ry = (int)random(snapshot.height);//you can pick only the areas that have text or the whole image bot a bit of hit&miss randomness
//check if it's the same colour as the text, if so, pick a random neighbour and also paint it black
if(snapshot.get(rx,ry) == color(0)) snapshot.set(rx+((int)random(randomSize,-randomSize)),ry+((int)random(randomSize,-randomSize)),0);
image(snapshot,0,0);
}
I have recently integrated in a HUD method into my XNA game project and when the method is called by the main Draw method it throws out a object disposed exception this has something to do with the two Drawstring used in the program.
The exception is thrown at spriteBatch.End() and says Cannot access a disposed object.
Object name: 'Texture2D'.
//initiation of the spritebatch
private SpriteBatch spriteBatch;
//game draw method
public override void Draw(GameTime gameTime)
{
ScreenManager.GraphicsDevice.Clear(Color.CornflowerBlue);
// Our player and enemy are both actually just text strings.
spriteBatch = ScreenManager.SpriteBatch;
tileMap.Draw(spriteBatch, camera);
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.AlphaBlend,
null, null, null, null,
camera.TransformMatrix);
DrawHud();
level.Draw(gameTime, spriteBatch);
spriteBatch.End();
// If the game is transitioning on or off, fade it out to black.
if (TransitionPosition > 0 || pauseAlpha > 0)
{
float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);
ScreenManager.FadeBackBufferToBlack(alpha);
}
base.Draw(gameTime);
}
the HUD method
private void DrawHud()
{
Rectangle titleSafeArea = ScreenManager.GraphicsDevice.Viewport.TitleSafeArea;
Vector2 hudLocation = new Vector2(titleSafeArea.X + camera.Position.X, titleSafeArea.Y + camera.Position.Y);
Vector2 center = new Vector2(titleSafeArea.Width + camera.Position.X / 2.0f,
titleSafeArea.Height + camera.Position.Y / 2.0f);
// Draw time remaining. Uses modulo division to cause blinking when the
// player is running out of time.
string timeString = "TIME: " + level.TimeRemaining.Minutes.ToString("00") + ":" + level.TimeRemaining.Seconds.ToString("00");
Color timeColor;
if (level.TimeRemaining > WarningTime ||
level.ReachedExit ||
(int)level.TimeRemaining.TotalSeconds % 2 == 0)
{
timeColor = Color.Yellow;
}
else
{
timeColor = Color.Red;
}
DrawShadowedString(hudFont, timeString, hudLocation, timeColor);
// Draw score
float timeHeight = hudFont.MeasureString(timeString).Y;
DrawShadowedString(hudFont, "SCORE: " + level.Score.ToString(), hudLocation + new Vector2(0.0f, timeHeight * 1.2f), Color.Yellow);
}
//method which draws the score and the time (and is causing the problem)
private void DrawShadowedString(SpriteFont font, string value, Vector2 position, Color color)
{
spriteBatch.DrawString(font, value, position + new Vector2(1.0f, 1.0f), Color.Black);
spriteBatch.DrawString(font, value, position, color);
}
As the exception says, the problem exists because one of the Texture2Ds you are using is being disposed before you are using it.
There are two things in the XNA API (that come to mind) that will dispose of a Texture2D: The ContentManager.Unload() method for any textures loaded by that content manager, and the Texture2D.Dispose() method. So check if your own code is calling one of these two functions at any point.
The exception will only be thrown when the Texture2D instance is "used". Because SpriteBatch batches together texture draws, the texture doesn't actually get used until you end the SpriteBatch (at which point it draws everything in one go). If you change to SpriteSortMode.Immediate SpriteBatch will stop batching sprites and will instead draw them "immediately" you ask it to. This will cause the texture to be used and the exception to be thrown at a Draw call instead of an End call, which should make it easier to identify which texture is being disposed of while still in use.
The code you have posted seems to be fine, I suspect the problem exists elsewhere in your code. The above information should help you identify where the problem is.
My guess is that something is happening in level.Draw that is disposing of a texture somewhere. It doesn't look like the drawhud method in particular is responsible
You mention though that you are sure it's caused by the drawstring methods ... if you comment those two out in particular does the error go away?
I need to know active screen DPI on Linux and Mac OS. I think on linux xlib might be useful, but I can't find a way how to get currect DPI.
I want this information to get real screen size in inches.
Thanks in advance!
On a mac, use CGDisplayScreenSize to get the screen size in millimeters.
In X on Linux, call XOpenDisplay() to get the Display, then use DisplayWidthMM() and DisplayHeightMM() together with DisplayWidth() and DisplayHeight() to compute the DPI.
On the Mac, there's almost certainly a more native API to use than X. Mac OS X does not run X Window by default, it has a native windowing environment.
I cobbled this together from xdpyinfo...
Compile with: gcc -Wall -o getdpi getdpi.c -lX11
/* Get dots per inch
*/
static void get_dpi(int *x, int *y)
{
double xres, yres;
Display *dpy;
char *displayname = NULL;
int scr = 0; /* Screen number */
if( (NULL == x) || (NULL == y)){ return ; }
dpy = XOpenDisplay (displayname);
/*
* there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
*
* dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
* = N pixels / (M inch / 25.4)
* = N * 25.4 pixels / M inch
*/
xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) /
((double) DisplayWidthMM(dpy,scr)));
yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) /
((double) DisplayHeightMM(dpy,scr)));
*x = (int) (xres + 0.5);
*y = (int) (yres + 0.5);
XCloseDisplay (dpy);
}
You can use NSScreen to get the dimensions of the attached display(s) in pixels, but this won't give you the physical size/PPI of the display and in fact I don't think there are any APIs that will be able to do this reliably.
You can ask a window for its resolution like so:
NSDictionary* deviceDescription = [window deviceDescription];
NSSize resolution = [[deviceDescription objectForKey:NSDeviceResolution] sizeValue];
This will currently give you an NSSize of {72,72} for all screens, no matter what their actual PPI. The only thing that make this value change is changing the scaling factor in the Quartz Debug utility, or if Apple ever turns on resolution-independent UI. You can obtain the current scale factor by calling:
[[NSScreen mainScreen] userSpaceScaleFactor];
If you really must know the exact resolution (and I'd be interested to know why you think you do), you could create a screen calibration routine and have the user measure a line on-screen with an actual physical ruler. Crude, yes, but it will work.
Here's a platform independent way to get the screen DPI:
// Written in Java
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.border.EmptyBorder;
public final class DpiTest {
public static void main(String[] args) {
JFrame frame = new JFrame("DPI");
JLabel label = new JLabel("Current Screen DPI: " + Toolkit.getDefaultToolkit().getScreenResolution());
label.setBorder(new EmptyBorder(20, 20, 20, 20));
frame.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
You can download a compiled jar of this from here. After downloading, java -jar dpi.jar will show you the DPI.