floorf(CGRectGetMinX(visibleBounds) / CGRectGetWidth(visibleBounds));
What is the monotouch version of the methods CGrectGetWidth and CGrectGetMinX?
Update Xamarin.iOS Unified API
Xamarin.iOS introduced the Unified API which now contains CGRect and friends inside CoreGraphics namespace.
CGRect is Mapped to System.Drawing.RectangleF (See Type Mappings)
So if you have your own System.Drawing.RectangleF
The code would look like
RectangleF visibleBounds = new RectangleF(0, 0, 10, 10); // Or your own instance of visibleBounds
float minx = visibleBounds.GetMinX();
float w = visibleBounds.Width;
Hope that helps
Alex
Related
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)
I noticed a strange behaviour with Direct3D while doing this tutorial.
The dimensions I am getting from the Window Object differ from the configured resolution of windows. There I set 1920*1080, the width and height from the Winows Object is 1371*771.
CoreWindow^ Window = CoreWindow::GetForCurrentThread();
// set the viewport
D3D11_VIEWPORT viewport = { 0 };
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = Window->Bounds.Width; //should be 1920, actually is 1371
viewport.Height = Window->Bounds.Height; //should be 1080, actually is 771
I am developing on an Alienware 14, maybe this causes this problem, but I could not find any answers, yet.
CoreWindow sizes, pointer locations, etc. are not expressed in pixels. They are expressed in Device Independent Pixels (DIPS). To convert to/from pixels you need to use the Dots Per Inch (DPI) value.
inline int ConvertDipsToPixels(float dips) const
{
return int(dips * m_DPI / 96.f + 0.5f);
}
inline float ConvertPixelsToDips(int pixels) const
{
return (float(pixels) * 96.f / m_DPI);
}
m_DPI comes from DisplayInformation::GetForCurrentView()->LogicalDpi and you get the DpiChanged event when and if it changes.
See DPI and Device-Independent Pixels for more details.
You should take a look at the Direct3D UWP Game templates on GitHub, and check out how this is handled in Main.cpp.
I'm trying to convert an iphone app that consists of 3 different asset sizes for three different screen sizes (base-iphone(320x480), mid-iphone(640x960) ipad(768x1024),high-ipad3) into one for android that utilizes these different assets based on the resolution of different devices.
The code utilizes the ipad/iphone Idioms and apportable overrides the UIDevice methods for this using the VerdeConfigIsTablet() method. It is very unclear how this is done. Is there any good resource to understand how each resolution is assigned and scaled?
Thanks
See the Apportable UIScreen docs.
Also, potentially useful is [[UIScreen mainScreen] bounds]:
(gdb) p [UIScreen mainScreen]
$2 = (struct objc_object *) 0x6acd5490
(gdb) p [$2 bounds]
$3 = {origin = {x = 0, y = 0}, size = {width = 800, height = 1205}}
EDIT: I tried using the push/pop thing, but now it crashes.
I have a feeling what I'm attempting to do is way off.. Is there any way to just get core graphics showing up on the screen? I need something thats able to be updated every frame, like drawing a line between two points that always move around..
Even if someone knows of a complete alternative Ill try it.
in .h
CGContextRef context;
in .m
in init method
int width = 100;
int height = 100;
void *buffer = calloc(1, width * height * 4);
context = CreateBitmapContextWithData(width, height, buffer);
CGContextSetRGBFillColor(context, 1, 1, 1, 1);
CGContextAddRect(context, CGRectMake(0, 0, width, height));
CGContextFillPath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
hud_sprite = [CCSprite spriteWithCGImage:image key:#"hud_image1"];
free(buffer);
free(image);
hud_sprite.anchorPoint = CGPointMake(0, 0);
hud_sprite.position = CGPointMake(0, 0);
[self addChild:hud_sprite z:100];
in a method I call when I want to update it.
int width = 100;
int height = 100;
UIGraphicsPushContext(context);
CGContextClearRect(context, CGRectMake(0, 0, width, height)); //<-- crashes here. bad access...
CGContextSetRGBFillColor(context, random_float(0, 1),random_float(0, 1),random_float(0, 1), .8);
CGContextAddRect(context, CGRectMake(0, 0, width, height));
CGContextFillPath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIGraphicsPopContext();
//CGContextRelease(ctx);
[[CCTextureCache sharedTextureCache] removeTextureForKey:#"hud_image1"];
[hud_sprite setTexture:[[CCTextureCache sharedTextureCache] addCGImage:image forKey:#"hud_image1"]];
free(image);
You are calling UIGraphicsPushContext(context). You must balance this with UIGraphicsPopContext(). Since you're not calling UIGraphicsPopContext(), you are leaving context on UIKit's graphics context stack, so it never gets deallocated.
Also, you are calling UIGraphicsBeginImageContext, which creates a new graphics context that you later release (correctly) by calling UIGraphicsEndImageContext. But you never use this context. You would access the context by calling UIGraphicsGetCurrentContext, but you never call that.
UPDATE
Never call free on a Core Foundation object!
You are getting a CGImage (which is a Core Foundation object) with this statement:
CGImageRef image = CGBitmapContextCreateImage(context);
Then later you are calling free on it:
free(image);
You must never do that.
Go read the Memory Management Programming Guide for Core Foundation. When you are done with a Core Foundation object, and you have ownership of it (because you got it from a Create function or a Copy function), you must release it with a Release function. In this case you can use either CFRelease or CGImageRelease:
CGImageRelease(image);
Furthermore, you are allocating buffer using calloc, then passing it to CreateBitmapContextWithData (which I guess is your wrapper for CGBitmapContextCreateWithData), and then freeing buffer. But context keeps a pointer to the buffer. So after you free(buffer), context has a dangling pointer. That's why you're crashing. You cannot free buffer until after you have released context.
The best way to handle this is to let CGBitmapContextCreateWithData take care of allocating the buffer itself by passing NULL as the first (data) argument. There is no reason to allocate the buffer yourself in this case.
I have a standard scene with the init method as follows:
#interface CommodoreScene : CCLayerColor
#end
#implementation CommodoreScene
- (id) init {
if (( self=[super initWithColor:ccc4(255, 255, 255, 255)] )) {
}
return self;
}
#end
However when I run the scene on my iPhone4, or the simulator half the screen goes black, the other half my layer color (white).
I'm currently running the scene with [_director pushScene:[CommodoreScene node]]; and running cocos2d-iphone 2.0.0.
- (id) init {
if (( self=[super initWithColor:ccc4(255, 255, 255, 255) width:480 height:320] )) {
}
return self;
}
Try that. The important part is of course the change in the call to super. You might still have an issue with [[CCDirector] winSize] reading properly in the -init method if you're in landscape (which judging from the bug you're experiencing - you are), at least I did on my tests. As I recall, this is a known bug of some kind, as it seems to read the winSize as portrait instead of landscape. You can fix this by doing the following:
CGRect rect = CGRectMake(0, 0, 480, 320);
CGSize size = rect.size;
// position the label on the center of the screen
label.position = ccp( size.width /2 , size.height/2 );
Using that newly created size instead of winSize in your -init method fixes the issue. Notice that if you create and position an element after initialization, such as in onEnter, this problem goes away and the winSize from the director reads properly. Odd bug, it is.
You can change content size of your color layer;
CGSize boxSize = CGSizeMake(sGame.winWidth, sGame.winHeight);
CCLayerColor *box = [CCLayerColor layerWithColor:ccc4(155,155,200,255)];
box.position = ccp(0.0f, 0.0f);
box.contentSize = boxSize;
[self addChild:box z:-6];