Hey everyone! I'm currently working on a script which detects the color of a few pixels on the screen about 30-60 times a second, to detect game states (health bar), live.
I'm doing this with Python, to integrate with OBS (a recording program).
I'm pretty new to Python, I've only worked with it for very short amounts of time.
I've looked on Stackoverflow for a small while and found someone using this script:
from PIL import ImageGrab
import time
time.clock()
image = ImageGrab.grab()
for y in range(0, 100, 10):
for x in range(0, 100, 10):
color = image.getpixel((x, y))
print(time.clock())
[Source]
Here, they use the 'for' loop in Python, with variable y and x, with Imagegrab imported.
I do not understand how 'for y in range(0,100,10)', or 'for x in range [...]' works. How does this notation work? How would I customize it to fit the pixels I want to track, which are specific to only like three, all on different locations? (I don't need more, I only need to track one because one is more than enough to see the color, right?)
Thank you guys in advance for your answers, you're awesome.
-- Lucas.
Top comments (1)
In Python, a
for
loop always takes a sequence to iterate over. This allows for a couple of optimizations in the language itself, but is mostly to allow for a concise expression of the very common case of looping over all the elements in alist
(or all the key/value pairs in adict
). As a result, the only syntax for afor
loop in Python isfor <var> in <sequence>:
, where<sequence>
is the sequence to iterate over (or a generator, but that's not exactly relevant here). You can pass in literally anything that implements thecollections.ABC.Sequence
base class, which includes lists, dictionaries (each element in the sequence evalues to one key-value pair from the dictionary), tuples, strings (each element in the sequence is a character in the string), bytes objects, and a couple of other native types (plus any class that implements the above mentioned base class).Obviously, this leads to complications when you just need to loop over a set of numbers. For that reason, Python (and most other languages that support this type of
for
loop) provides a native sequence type representing a range (in the mathematical sense) of numbers. The way you create an object of this type is with therange()
function. The full syntax for invoking this function isrange(start, stop, step)
, wherestart
is the value to start with (defaults to 0 if both it andstep
are omitted),stop
is an exclusive upper limit, andstep
is how much to add tostart
on each iteration (defaults to 1 if it is omitted).Thus,
range(10)
expressed as a list would be all integers from 0 to 9.range(1, 5)
would be the numbers 1 through 4, andrange(0, 100, 10)
would be every multiple of 10 from 0 through 90.Ranges can also count downwards by specifying a negative
step
value and appropriatestart
andstop
values.Ultimately, this means that the following Python code:
is functionally equivalent to the following JavaScript (or C, or Java, or any of a number of other languages) code:
And this:
is equivalent to:
Putting this together, the code you posted will look at every tenth pixel on the X axis at Y=0 up to and including X=90, then do the same for every tenth Y value up to and including 90. If you're just looking to get a rough estimate of the colors within a box of pixels starting at 0,0 and ending at 90,90, this is reasonably effective. You can tweak the
start
,stop
, andstep
values on each loop to check any rectangle you want on the screen with any granularity you want.However, this won't work if you need to check an oddly shaped region, like the health bars present in a number of more 'modern' games (like the Borderlands series for example, where the 'high' end of the health bar is at an angle, and the 'top' of the health indicator in the bar matches that angle, which would require you to only look at the bottom few rows of pixels of the health bar to get an accurate reading). In those cases, you'll have to get more creative about how you manipulate the coordinates, either by directly creating a list of the coordinates you want to check, or using some math to manipulate them inside the loops.