Sikulix : Compare a image and a screen of website - sikuli

I use sikulix and I want to check if a region of a website is red or green.
So I have taken a picture of the part of the website when is red (negatif.png)
A another region for the check of the color. But it doesn't work.
img_negatif = "negatif.png"
profit = Region(1342,212,175,21)
if profit == img_negatif:
click(Location(3406,1420))
else:
click(Location(23,1420))
Everytime sikulix take the else.

You cannot compare regions strictly by color. You can see my answer here (this is from years back but I think it's still relevant).
Sikuli compares the regions with pixel to pixel precision (you can set a similarity level if the images slightly differ but that's not the case). So having selected an area with just color and no other pattern will not work.

Wait for 3 second for negatif and if appear ...
if exists(img_negatif, 3):
click(Location(3406,1420))
else:
click(Location(23,1420))

You can search a region for color with Brobot, an open-source automation framework for Java that wraps SikuliX functions. Brobot references OpenCV for its color functionality. The Brobot documentation gives more detailed information on the framework. Additionally, there is a page in the documentation on color searches. For a summary of Brobot's color functionality, you can read this StackOverflow answer.
Finding the Red Region
public Matches find() {
ActionOptions actionOptions = new ActionOptions.Builder()
.setAction(FIND)
.setFind(COLOR)
.build();
return action.perform(actionOptions, redRegionState.getRedArea());
}
Elements of this code block:
Matches, the return value, holds information about the individual matches and the action.
ActionOptions is used to configure the action. Here, we tell it we want a FIND operation and we want to find by COLOR.
The Action class is the Brobot class that performs actions. The result of an action is always a Matches object. The function action.perform requires as parameters (1) the action configuration and (2) the object(s) to act on. Here, we pass in our actionOptions variable and our image.
The image “negatif.png” is stored in a Brobot variable called redArea, located in the state RedRegionState, and called with redRegionState.getRedArea().
The average pixel color of all pixels in “negatif.png” is calculated and this color is searched for on-screen.
The classes Action and RedRegionState are passed to this class with dependency injection.
The Red Image
You could also declare the Brobot variable containing “negatif.png” locally but one of the main benefits of Brobot is its ability to simulate the environment and test code with mock runs. This requires creating states that group associated images. Inside the state, the image definition would look like this:
#Component
#Getter
public class RedRegionState {
…
private StateImageObject redArea = new StateImageObject.Builder()
.withImage("negatif.png")
.withSearchRegion(1342,212,175,21)
.build();
…
}
Including a search region in the image variable means that the image will be searched for in this region on-screen unless a search region is added to the action configuration (the ActionOptions variable).
Clicking after Searching
public void click() {
int x = find().isSuccess() ? 3406 : 23;
action.perform(CLICK, new Location(x, 1420).asObjectCollection());
}
Elements of this code block:
Each action (FIND, CLICK, DEFINE, etc.) has its own success condition, and the result is stored in the Matches variable. It can be called with the boolean function .isSuccess().
As above, action.perform takes as parameters the action configuration and the object(s) to act on.
Usually an ActionOptions variable is required for the first parameter. However, an enum representing the action (here, CLICK) can be passed directly if you wish to use the action's default options.
The second parameter usually takes an ObjectCollection variable. In some cases, as with the image redArea, the object can be passed directly. Here, the object acted on, a Location, is converted to a singleton ObjectCollection and passed as the second parameter.
When building a more complex automation application, it would make sense to include the Location variables as well in states. Most likely, the Location at (3406, 23) would be in RedRegionState, as this Location has a special meaning when redArea is visible.
Disclaimer: I'm the developer of Brobot. It's free and open source.

Related

How to control NPC animation from GUI button click (Unreal)

I have a number of animation sequences connected to an ENUM Blend Pose node. I can manually switch this enum value in the Anim Preview panel.
Now I wish to control this enum value from a bunch of buttons added to a User Widget. The widget is instantiated within the Level BP.
When I edit the onClick events on the buttons, I do not know how to get a reference to my enum variable (which I have exposed as Public in the Anim Blueprint's settings).
Essentially, each button is designed to change this variable to a unique value, which then should cause the appropriate animation to play within the Blend Pose.
How do I let the Widget have access to that variable? Or vice versa, how could I create a variable on the blueprint that can be used to set the Enum value on the Blend Pose?
Please note that I am using the visual blueprint editor, not C++ at this time.
I am coming from a 100% C++ background, so I may have some options on my mind that are not entirely working in BP, but we'll get to that.
I would not use the level blueprint at all for anything. Instead use your GameMode or GameState for spawning the UserWiget. The GameMode and GameState are accessible via the GetGameMode node. Keep in mind that in multiplayer scenarios, only the GameState is available to all while the GameMode can only be accessed by the host or dedicated server, but that is probably irrelevant for you.
After spawning the widget assign it to a public variable of its type, so you can get it from the outside.
In your actor (not animation blueprint) you can access the GameMode easily using the GetGameMode node. You have to cast it to your specific GameMode to get to the variable of the widget. For the GameState use GetGameState.
Now you have multiple options to connect everything together. You could for example pass your actor to the UI and store it as a variable there. The UI can then simply call a custom function like "SetAnimationState" that you create on the actor for each button. Your actor can pass the enum value down to the animation blueprint. Using your skeletal meshes GetAnimInstance node.
This is one simple way I can think of. You could also work with an event dispatcher that broadcasts whenever a button is pressed and your actor is subscribed to it to get notified.
I hope any of this helps.
Building on #MaxPlay's answer, here's my final (possibly sub-optimal) solution with images for posterity. I'll probably stumble upon this answer in a few years like I do with some of my other SO posts from years ago ;)
First, the Anim BP on my Actor (note that this is not the player's pawn but just another mesh in the world) which just sets up the Blend Poses, using an Enum.
It's really vitally important here to make sure the variable that holds the Enum is made public. You do that by clicking the eye icon next to the variable name. If you don't do this, no external class (blueprint) gets to read or set the value of that variable.
This is a screen grab of the variables portion of the Anim BP's properties panel.
And here's that Enum, which you can create as a blueprint. I've used it to have a nice textual reference that has semantic meaning. Also makes it easier to link to the buttons later.
Now we get into the heart of the matter - the Actor Blueprint. I just wrapped this blueprint around my Skeletal Mesh Asset by selecting it in the viewport and then using the Blueprint menu to convert it.
In the image below you can see the Details panel of that Actor Blueprint, showing how it composes the Anim BP
Next is the magic step!
I created a function on the Actor Blueprint that other blueprints can call with 1 parameter - the ENUM that I defined earlier. The goal of this function is as a public setter on the Anim BP's public variable. I wasn't able to expose this public variable outside the hierarchy, so this gets around that visibility issue by delegating the responsibility for setting the Anim BP's variable to its Actor BP.
Since the Actor Blueprint has a reference internally to its Skeletal Mesh's currently assigned animation blueprint, and that Anim BP's variable has been made public, it gets to set it directly.
The goal is to pass a reference to this Actor BP to the Widget so the Widget's buttons can call this method (function) at a later time.
Over on the Widget side, I'm exposing a variable, cast as that specific animation blueprint (so that the Widget knows about the SetAnimFromEnum method). I'll be setting that variable in a moment.
Before I do, here's how the Widget Blueprint is set up - very simply, each button calls the same SetAnimFromEnum() method and just passes a different value from the enum.
If you had a million buttons, this would not be efficient and you might want to invest in a bit more complex blueprinting (I'm not yet at that level) - ideas here are to somehow parse the name / label of the button and derive the appropriate enum from it, or revert to an integer-based Blend Pose node and add a property to each button, etc.
And finally, the glue that holds it all together: the Actor Blueprint that instantiates the widget. This is the part I don't like in my solution - in my mind, the widget shouldn't be so tightly coupled (composed) with the Actor BP. But I would have had to jump through more hoops if using the Global GameMode or GameState Blueprints, and this is just a proof-of-concept so I'm keeping it simple, if slightly messy.
The Animation Blueprint below shows me instantiating the Widget and using the return value to both add it to the Viewport, as well as then accessing the widget's public variable designed to hold a reference to this Actor Blueprint and setting it. That creates the link between these two blueprints allowing the Widget to then call a method on the Actor.

Godot: How to disable/overwrite inherited function?

I am trying to come up with an efficient way to organize clickable menus for the objects in my game. I made a Menu class, from which all possible menus inherit:
class_name Menu extends Control
#contains functions (for buttons) that all menus have in common
func open_menu():
pass
func close_menu():
pass
To make a menu specific to buildings, I inherit all functionalities from the Menu class:
class_name BuildingMenu extends Menu
# contains functions specific to all buildings
func upgrade_building():
pass
func delete_building():
pass
# ... many more ...
Now here's the problem: My HQ is literally just another building with a few extras and the main difference that it can't be deleted, so I'm thinking of inheriting from BuildingMenu. Is there a way to disable the inherited delete_building() function in the HQMenu script?
class_name HQMenu extends BuildingMenu
func delete_building():
# overwriting inherited function like this does not work...
# ... some HQ specific stuff here ...
I could just inherit from Menu and then copy paste everything from BuildingMenu except the delete_building() method, but this seems somewhat clumsy because now I have to edit two files if I want to change/add any building functions.
What is the correct way to do this?
SOLUTION:
Thanks to the suggestion by Thearot I've decided to move the delete_building() function into a new class from which all the regular (non HQ) buildings inherit:
Now here's the problem: My HQ is literally just another building with a few extras and the main difference that it can't be deleted, so I'm thinking of inheriting from BuildingMenu. Is there a way to disable the inherited delete_building() function in the HQMenu script?
This sounds like a violation of Liskov Substitution Principle. From a purely object oriented point of view, it would be preferible to make another class for a subset of buildings with what they have in common, than to have one building inherit from another if it has to disable some methods.
If your base class for all buildings implies that some buildings have to disable some methods, then it does not really have the methods common for all building, it has some extra ones.
To be clear, here I'm suggesting to add another extra intermediary class, and that way you don't have to delete nor duplicate methods.
If that is not an option for you… Congratulations! you have made a mess system complex enough that some kind of component based system begins to make sense. But don't jump the line, don't fret, it is OK.
If I understand correctly you have some contextual menus that show different options depending on what is selected or what you click on, right?
That means that the options are variable. Thus, use a variable. Add an Array field that has the names of the methods that should be linked to the menu. Then have the menu system discover the options by reading that Array, and connecting to functions with the names specified there.
And how you do add or remove options? You add them or remove them form the Array. Simple. You can populate the Array in _init.
To be clear, you can check if an object has a method with has_method. You call a method by name with call, or - of course - you could connect signals to them with connect (if prefer to populate an static menu for the object instead of having a dynamic one). Yes, I'm suggesting late binding.

Corona use object properties from Tiled layers

I am new to Lua scripting, and game development. So please I am just a noob in Lua.
I have searched the net for solutions to my problems, without any luck.
I use Photoshop, Corona, Dusk, json and Tiled on windows7.
I am creating a "board" like game, i.e. Setlers. I am using a world map, as the background. The background image of the game area is a world map (world.png file). I have no problem here.
I would like to create transparrent clickable objects matching the countrys borders on my gamemap with all parameters and values (I have added in Tiled) stored in the object. So When the player clicks on the country the transparrent object (on top of the map) is the one clicked and an eventlistener acts on the click.
In Tiled I can create all the objects I need, naming them + assigning parameters and other values.
If I add object.alpha value in Tiled, the alpha value is passed on to corona and working there.
How can I read these data from the json/tmx file in Corona and adding them to a lua table?
The way I am thinking to use the Tiled map and its objects, is to create one polyline trace of each country’s border (creating one object per country). Then place each “country traced object” on top of the world.png map, also naming the object with the countrys name like “object.name = TileBritannia” and also the other properties for use in game.
My problem is getting the objects info, like object.name, and an eventlistener reacting to a click on the object.
Is a polyline the right way to create a clickable area on a map, when I use a png file as a background image?
What is the best way to create a country border objects, in one layer or with all countries as individual object layers in Tiled.
Can I create one layer with sub objects and still access them in my code?
How do I get the object name and other properties, set in Tiled.
When I try to use the (local britannia = tiledMap:load("britannia.json")) the "load" is not working, getting a nil value.
I am looking for a code that will extract/get/read the object.name i.e. “objBritannia” or "TileBritannia". from the json/tmx file.
When I try to read the different parameters from the json file, I don't get the result I expect. I get the result = function: 046A73B0, was hoping for an object name of some sort.
Please provide links to or code example.
I have edited the question.
Thanks
For questions 1 and 2: I have not used Tiled, but based on Corona Tiled, you have the right strategy in mind. That page makes me think that you can just use tap event listener to detect tap. If you are having issues with the example on that web page, please update your question to be more specific. If tap event handling doesn't work (maybe you're talking about a different Tiled lib), look a Polygon fill and Point in Polygon detection, because that's basically what you need to do. Try some stuff from there. If it still doesn't work for you, then update your question with specifics otherwise it will be likely get closed (it is a little too broad as it is).
For #3, Lua is a dynamic language that supports adding properties to objects in one line. So upon the example on the Corona Tiled page, all you would have to do is
tiledMap = require("tiled")
local britannia = tiledMap:load("britannia.json")
britannia.name = "Britannnia"
local Zulu = tiledMap:load("zulu.json")
zulu.name = "zulu"
Naturally you will probably have a whole bunch so you will create a function that you call for each tile. It's not clear what map.layer["objBritannia "].nameIs("TileBritannia") is supposed to do so I can't comment.

Issue with Document Class and Tutorial

So I've been following this tutorial on AS3 and Flash. Its been going well until, note I have tried to contact the writer of the tutorial and had no reply. Here's what it tells me to do;
Right-click PlayScreen in the library, select Properties, and check Export for ActionScript. This time, instead of accepting the default value, enter the name of your document class. Click OK.
So it pops up an error, first we’ll have to make a new document class, since no two different objects can share the same class. Cancel the Properties box.
Hit File > New and select ActionScript File. Enter the (by now familiar) code.
Save this in the Classes directory as DocumentClass.as. (There’ll be no confusing the purpose of this file!) Now, back in your FLA, change the document class to DocumentClass.
Check everything’s fine by clicking that pencil icon — if it’s all OK, that should bring up the AS file that you just created.
// So this bits all fine, its the next that i'm stuck with:
Now you can set the PlayScreen‘s class to AvoiderGame. So do so!
// So I go ahead into the properties and change the name but then it pops up with the same error as before: 'Please enter a unique class name that is not associated with other library symbols'
What does this mean!? How do I resolve this!?
Full tutorial here:Flash Tutorial
Its hard to tell what you are trying to accomplish without knowing what all the parts you are referring to actually do, which are objects in the library and which are classes, but maybe this can help:
First of all, document class in AS3 typically refers to the project's main set of code that initializes the app. This class can be called anything but is often called Main, and is entered in the property panel that is displayed when you click the projects main stage in the field called class.
Now, when linking a class to an object in the library, its a little different. In the library object's property panel, tick the box for Export for Actionscript, and put a unique name in the top box. This is what you reference in your code to call it, like new somethingOrOther() or using the pic below as an exaample, new Ball(). The second box is the base class, pathed to where it lives in your code base. This is the class you will write that actually controls the object you've linked the class to. Giving a linked object a base class and a unique identifier allows you to use the same base class for multiple linked objects.
Note that when you do this approach, Flash will warn you that there is no class associated with Ball and one will be created for you. Don't worry, this is normal behavior. If you set this up properly, your object will still be controlled by its base class.

Storing Multiple Images In A Variable With Action Script 3 In Flash Builder 4.5

I have a flash assignment that I need help getting started, any advice would be greatly appreciated. The assignment is to create an application for playing a card game, I have to create an MXML component that has two variables, one variable stores the image of the back of a playing card, the other variable has t store all 52 options of a front facing card (the second variable will store over 50 images).
I've written the variable for the back of the card image like this:
public var backOfCard:Image = new Image();
backofCard.source = 'asset/backImage';
However I get an undefined variable error (1120: Access of undefined propery variable img1), I feel like there's something small that I'm missing here, but I was wondering if anyone could spot it.
I'd also like to know if I should use the same method for each jpg image for the front of the cards, it seems like it would be a lot of repetitive code aside from the change in filename for the front of the card images.
Here's a snippet of the homework assignment, again I just need help getting this part correct, I really appreciate any help with this.
Your job is to supply the custom component named Card. Create the
component by using File → New → MXML Component. In the popup dialog
box
leave the Package blank
Name the component Card
Base Card on spark.components.Image
What goes into the Card component?
For each card, we'll want to be able to show the front face of the
card, or its back face. That means each card should have a place to
store information about what file to show as its front face, and what
file to show as its back face.
To do this, create two variables in the Card component to store the
file names. You might call these variables backImage and frontImage.
Your access modifier is what's bothering me.
If you're creating these definitions in your class file, then the first statement works:
public var backOfCard:Image = new Image();
But if you're in one of the methods, usually the constructor (sometimes called the ctor), or any other method of the application, you could use the 2nd statement:
backofCard.source = 'asset/backImage';
But the combination of both is what I think is confusing. Because the "access modifier" (i.e. public, private, internal, protected) is what you use to define variables and methods within a class. And since you're putting both side-by-side (a definition and an assignment statement), I think you're mixing when to declare them.