Processing: How do i create an object every "x" time - function

What I want to do is to create a new planet in my system for example every 10 seconds and that it starts to move and also prints a "hello" . At the end I want that the 8 planets (ellipses) will be moving together.
I try to use delay(); but I failed .
Can someone help me please?
Planet [] planetCollection = new Planet [8];
float [] wid2 = {100,200,300,400,500,600,700,800};
float [] hig2 = {50,75,100,125,150,175,200,225};
int [] colorR = {100,800,300,400,500,600,700,800};
int [] colorG = {50,225,100,125,150,175,200,225};
int [] colorB = {50,225,100,125,150,175,200,225};
int [] size = {10,12,14,16,18,20,22,24};
int lastTime =0;
int contador =0;
void setup (){
size (1600,1600);
smooth();
//INITIALIZE
for (int i=0 ; i<planetCollection.length; i++){
planetCollection [i] = new Planet(wid2[i], hig2[i], colorR[i],
colorG[i], colorB[i], size[i]);
}
}
void draw (){
background (0);
//CALL FUNCIONALITY
for (int i=0 ; i<planetCollection.length; i++){
planetCollection [i].run();
}
}
class Planet {
//GLOBAL VARIABLES
float val;
float x = 0;
float y = 0;
float wid2;
float hig2;
float speed;
int colorR;
int colorG;
int colorB;
int size;
int centerx = width/2;
int centery = height/4;
//CONTRUCTOR
Planet(float _w, float _h,int _colorR,int _colorG,int _colorB, int _size){
wid2=_w;
hig2=_h;
colorR= _colorR;
colorG= _colorG;
colorB= _colorB;
size = _size;
speed=10/(2*PI * sqrt ((pow(wid2,2)+pow (hig2,2)/2))); ;
}
//FUNCTIONS
void run (){
move();
display();
}
void move (){
x= sin (val);
y= cos(val);
x *=wid2;
y *=hig2;
//SUN/CENTER
noStroke();
fill (255,238,41);
ellipse (centerx,centery,40,40);
if (dist (mouseX,mouseY,centerx,centery)<20){
if(mousePressed){
speed =0;
}
}
//
x+= centerx;
y+= centery;
val += speed;
}
void display (){
//PLanets
fill(colorR, colorG, colorB);
ellipse(x, y, size, size);
///Orbits
noFill();
stroke(255);
ellipse(centerx, centery, wid2*2, hig2*2);
println ("posicionx "+x);
println ("posiciony "+y);
println ("width "+wid2);
println ("high "+hig2);
println ("val "+val);
println ("speed "+speed);
}
}

You can use the modulo % operator along with the frameCount variable inside the draw() function to do something every X frames.
Here is an example program that draws little circles most frames, but draws a big circle every 60 frames:
void setup() {
size(500, 500);
background(0);
}
void draw() {
ellipse(mouseX, mouseY, 10, 10);
if (frameCount % 60 == 0) {
ellipse(mouseX, mouseY, 50, 50);
}
}

You can build a timer for counting seconds using a helper variable and the in-built variable frameRate. (Note that this solution ensures that you truly count seconds independent on your machine's current workload.)
frameRate tells you how many cycles Processing is currently performing per second (one cycle = one execution of draw, also called one frame). This is usually 60 (frames per second) but can also be lower depending on other processes on your machine (e.g. when running video processing, 3D games etc. the frame rate goes down).
Here's a snippet to see what your current frameRate is:
void draw() {
println(frameRate);
}
And here's the timer using a helper variable counter which is reset every second. You should see a new dot appear on the console output every second.
int counter = 0;
void draw() {
if (counter > frameRate) {
print(".");
counter = 0;
} else {
counter++;
}
}
To make it count every 10 seconds you can just change the if condition to "counter > 10 * frameRate".

Related

Editing a function within mousePressed

I'm a beginner working with Processing trying to create a moving cloud sketch. They are to appear on mouseClick, and horizontally move across the screen.
void mousePressed() {
int newCloud {
xpos: mouseX;
ypos: mouseY;
}
clouds.push(newCloud);
}
Here is the area I'm unable to fix, trying to work out the mousePressed part.
and here is my full code! It seems a simple fix but I've tried a bunch of ways rewriting it without succsess.
int[] clouds;
int cloudx;
int cloudy;
int xpos, ypos;
void setup() {
size(600, 600);
int cloudx=mouseX;
int cloudy=mouseY;
}
void draw() {
background(100);
for (int i = 0; i < clouds.length; i++) {
int[] currentObj = clouds[i];
cloud(currentObj.xpos, currentObj.ypos, currentObj.size);
currentObj.xpos += 0.5;
currentObj.ypos += random(-0.5, 0.5);
if (clouds[i].xpos > width+20) {
clouds.splice(i, 1);
}
}
}
void makeCloud (int x, int y){
fill(250);
noStroke();
ellipse(x, y, 70, 50);
ellipse(x + 10, y + 10, 70, 50);
ellipse(x - 20, y + 10, 70, 50);
}
void mousePressed() {
int newCloud {
xpos: mouseX;
ypos: mouseY;
}
clouds.push(newCloud);
}
I had tried to make a new function, though the clouds wouldnt show, I also tried calling the makeCloud function though i know I need to be updating within this new function. Overall, I need help with how to write this statement for newCloud in the mousePressed function.
Your code is irreparable for many reasons.
int[] clouds; will create a reference for Array of single integers, not objects,
void makeCloud (int x, int y){...}, will just draw some ellipses,
clouds.splice(i, 1); inside an Array will not work at all,
This is a working reconstruction of Your problem:
ArrayList<Cloud> clouds = new ArrayList<Cloud>();
void setup() {
size(600, 600);
}
void draw() {
background(100);
drawClouds(clouds);
removeExcessClouds(clouds);
}
/**
** Cloud class
**/
class Cloud {
float xPos;
float yPos;
Cloud(float x, float y) {
xPos = x;
yPos = y;
}
void draw() {
fill(250);
noStroke();
ellipse(xPos, yPos, 70, 50);
ellipse(xPos + 10, yPos + 10, 70, 50);
ellipse(xPos - 20, yPos + 10, 70, 50);
}
void positionUpdate(float deltaX) {
xPos += deltaX;
yPos += random(-0.5, 0.5);
}
}
void drawClouds(ArrayList<Cloud> cds) {
float wind = 0.5;
for (Cloud cd : clouds) {
cd.draw();
cd.positionUpdate(wind);
}
}
void removeExcessClouds(ArrayList<Cloud> cds) {
int cdAmount = clouds.size();
for (int i = 0; i<cdAmount; i++) {
if (clouds.get(i).xPos > width+20) {
clouds.remove(i);
cdAmount = clouds.size();
}
}
}
void mousePressed() {
clouds.add(new Cloud(mouseX, mouseY));
println(mouseX + ", " + mouseY + " : " + clouds.size());
}
Note:
global List initiation:
ArrayList clouds = new ArrayList();
List proper iteration:
for (Cloud cd : clouds) { foo(cd); }
draw method inside a Cloud,
passing values when calling methods.
So, now You can iterate over a List of Objects, and call a draw method inside each Cloud.
As said in the other answer, you will need to refactor your code to use objects.
This looks like an atempt at a JS object literal - Java doesn't use them.
int newCloud {
xpos: mouseX;
ypos: mouseY;
}
You need to instance a Class:
Cloud myCloud = new Cloud(0,5); // You create a new variable of the Cloud type and initialize it with a new Cloud object (essentially calling the constructor)
class Cloud{
int posX, posY;
Cloud(int px, int py){ // This is called a constuctor and its the way a new instance is created
this.posX = px;
this.posY = py;
}
}
Than for the array of clouds you need an ArrayList of Clouds:
ArrayList<Cloud> clouds = new ArrayList<Cloud>();
in the mousePressed event you than just add the new cloud to the arraylist:
clouds.add(myCloud);

Can I send tone() function wirelessly?

I have a simple RPM Simulator (opensource) that generates values through the tone() function.
I need to send the RPM wirelessly through an nrf24l01 to a second Arduino that uses the RPM as a shiftlight, both come from chippernut.
The tone() function only sends to the pin, trying to read the values did not work.
How can i get the value of x (RPM) after it leaves the tone function?
I have tried reading it through analogRead, digitalRead, BitRead, tried printing the value of x which stays constant, to no avail, and it updates very slowly if it reads the output pin.
This is the code:
float RPM_MIN = 2500;
float RPM_MAX = 8000;
int Accel_Rate = 20;
float pulses_per_rev = 2.0; // make sure to keep the decimal
boolean accel = false;
float x;
long previousMillis = 0;
unsigned long currentMillis=0;
//float RPM_PRINT; //my addition to get a value to print
void setup() {
Serial.begin(57600);
pinMode(5, OUTPUT);
RPM_MIN = (RPM_MIN / 60);
RPM_MAX = (RPM_MAX / 60);
x = RPM_MIN;
}
void loop() {
while (accel==false){
currentMillis = millis();
if(currentMillis - previousMillis > Accel_Rate) {
previousMillis = currentMillis;
x++;
tone(5,x*pulses_per_rev);
if (x>RPM_MAX){accel=true;}
}
}
while (accel==true){
currentMillis = millis();
if(currentMillis - previousMillis > Accel_Rate) {
previousMillis = currentMillis;
x--;
tone(5,x*pulses_per_rev);
if (x<RPM_MIN){accel=false;}
}
}
//RPM_PRINT = x*pulses_per_rev;
//RPM_PRINT = digitalRead(5);
//RPM_PRINT = analogRead(5);
//Serial.println(RPM_PRINT);
}
Expected Result is a Value between 2000-8000 that is constantly changing
actual result is 1/0 or 81,33 or 4,1 or 900-980 updating once every few seconds.
How can I solve?

Explanation of test case in the prisoner wall jump program

This would be the general problem statement:
A prisoner escapes from the jail by jumping over N walls each with height of each wall given in an array. He can jump x meters of height, but after every jump he slips y meters due to some uncontrollable factors(wind, slippery wall, etc).
Similar problem statement mentioned here
The programming task given was to debug a function which included four parameters -
NoOfJumps(int x, int y, int N, int Height[])
Number of meters he jumps
Number of meters he slips down the wall
Number of walls
Height of the walls as an array
The first test case was for parameters - (10, 1, 1, {10})
10 being the meters he jumps, 1 meter he slips down, Number of walls being 1, and height of the wall being 10. Now:
effectiveJump = x - y = 9.
So he would have to jump twice to jump over the walls. So, this function should return 2 (total number of jumps required to escape).
There was also another test case for the parameters - (3, 1, 5, {20,5,12,11,3})
3 being the meters he jumps, 1 meter he slips down, Number of walls being 5, and height of the walls given as 20m, 5m, 12m, 11m, 3m. Now:
effectiveJump = x - y = 2.
We were given the output for the above parameter values as 24.
NoOfJumps(3, 1, 5, {20,5,12,11,3})
I can't understand how this output value is obtained. How exactly are the walls arranged?
I can only think of one solution for the corner case, i.e, when the person jumps over the wall
(when (x) > remaining height of the wall),
he should not slip down else I can't obtain the required solution.
For example, in the second test case at first wall, when the person is at 18m height, and he jumps 3m to 21m and doesn't slip down as he has crossed that wall. Next he starts jumping from 21 and not 20. The sequence of jumping would be :
0->2->4->6->8->10->12->14->16->18->21->23->26->28->30->32->34->36->39->41->43->45->47->50->53
Assuming walls at height, 20, 25, 37, 48, 51.
Is this a correct assumption for solving the problem?
C code on given case 2, will work for case 1 on changing the
parameters to (10,1,1,10).
#include<conio.h>
#include<stdio.h>
int jump(int x,int y,int n,int z[]);
int jump(int x,int y,int n,int z[])
{
int i, j, countjump, total = 0, extra = 0;
clrscr();
printf("\n%d\n", n);
for (i = 0; i < n; i++) {
printf("\n%d", z[i]);
}
printf("\n");
for (j = 0; j < n; j++) {
countjump = 1;
z[j] = z[j] + (extra) - x;
while (z[j] >= 0) {
z[j] = z[j] + y;
z[j] = z[j] - x;
countjump = countjump + 1;
if (z[j] < 0) {
extra = z[j];
}
}
total = (countjump + total);
}
return total;
}
void main()
{
int res, manjump = 3, slip = 1, nwalls = 5;
int wallheights[] = {20, 5, 12, 11, 3};
clrscr();
res = jump(manjump, slip, nwalls, wallheights);
printf("\n\ntotal jumps:%d", res);
getch();
}
Try this code. May not be optimized
$input1 = Jump Height
$input2 = Slipage
$input = Array of walls height
function GetJumpCount($input1,$input2,$input3)
{
$jumps = 0;
$wallsCrossed = 0;
while($wallsCrossed != count($input3)){
$jumps++;
$input3[$wallsCrossed] = $input3[$wallsCrossed] - $input1;
if($input3[$wallsCrossed] > 0){
$input3[$wallsCrossed] = $input3[$wallsCrossed] + $input2;
}else{
$wallsCrossed++;
}
}
return $jumps;
}
The walls come one after another. After jumping wall one the position should start from zero and not from the last jump height. For the first case the output should really be 1 as the height and jump are same. In the second test case, 24 is the right output.
I've seen the exact same question on techgig contest. For the first test case the output should be 1. The test case had been explained by themselves where there is no slipping if the jump and height are same.
Try this
You don't require the number of walls as it equals to size of array
public class Jump {
public static void main(String[] a) {
int jump = 3;
int slip = 1;
int[] hights = {20,5,12,11,3};
int count = 0;
for (int hight : hights) {
int temp = hight - jump;
if (temp >= 0) {
count = count + temp / (jump - slip)+1;
}
if (temp % (jump - slip) > 0) {
count++;
}
}
System.out.println(count);
}
}
Logic is here Plz check if this solves your problem.
package puzeels;
public class Jump
{
int jump=6;
int slip=1;
int numberOfWals=4;
int height[] ={21,16,10,5};
static int count=0;
int wallheight=0;
private int findJump()
{
for(int i=0;i<height.length;i++)
{
wallheight=height[i];
while((wallheight>0))
{
count=count+1;
wallheight=wallheight-(jump-slip);
System.out.println(wallheight+" "+count);
}
System.out.println("Out of while loop");
}
return count;
}
public static void main(String arr[])
{
Jump obj = new Jump();
int countOfJumps=obj.findJump();
System.out.println("number of jumps is==> "+countOfJumps);
}
}
You can use this one.
Sample Code
public static int calculateJumps(int X, int Y, int height[]) {
int tn=0,n;
for(int i=0; i<height.length; i++) {
if(height[i]<=X) {
tn+=1;
continue;
}
n=((height[i]-X)/(X-Y));
n+=height[i]-((X-Y)*n)==X?1:2;
tn+=n;
}
return tn;
}
You need to pass only X , Y and Array than you can get you output.
I think 12 is a wrong answer, as I tried this code I got 11, last jump doesn`t have a slip:
public static void main(String [] args) {
int T;
int jcapacity, jslip, nwalls;
//BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
Scanner sc = new Scanner(System.in);
T = sc.nextInt();
jcapacity = sc.nextInt();
jslip = sc.nextInt();
nwalls = sc.nextInt();
int [] wallHeightArr = new int [nwalls];
for (int i = 0; i< nwalls; i++) {
wallHeightArr[i] = sc.nextInt();
}
sc.close();
while(T-->0) {
int distance = log(jcapacity,jslip,wallHeightArr);
System.out.println(distance);
}
}
private static int log(int jcapacity, int jslip, int[] wallHeightArr) {
// TODO Auto-generated method stub
int distance = 0;
for(int i = 0; i< wallHeightArr.length; i++) {
int cHeight = 0;
int count = 0;
while (wallHeightArr[i] - cHeight > jcapacity) {
cHeight += (jcapacity - jslip);
count++;
}
count++;
distance += count;
}
return distance;
}
def jumpTheifCount(arr, X, Y):
jump = 0
remheight = 0
for i in range(len(arr)):
if X == arr[i]:
jump = jump + 1
continue
if X < arr[i]:
jump = jump + 1
remheight = arr[i] - X + Y
if remheight > X:
jump = jump + 1
remheight = arr[i] - X + Y
if remheight < X:
jump = jump + 1
continue
return jump
arr = [11, 10, 10, 9]
X = 10
Y = 1
print(jumpTheifCount(arr, X, Y))
check if this solves your problem
def GetJumpCount(jump, slips, walls):
"""
#jump:int, Height of 1 jump
#slips:int, height of slip
#walls:array, height of walls
"""
jumps = []
for wall_height in walls:
wall_jump = 1
wall_height -= jump
while wall_height > 0:
wall_height += slips
wall_height -= jump
wall_jump += 1
jumps.append(wall_jump)
return sum(jumps)

Efficiently XOR two images in Flash compile target

I need to XOR two BitmapData objects together.
I'm writing in Haxe, using the flash.* libraries and the AS3 compile target.
I've investigated HxSL and PixelBender, and neither one seems to have a bitwise XOR operator, nor do they have any other bitwise operators that could be used to create XOR (but am I missing something obvious? I'd accept any answer which gives a way to do a bitwise XOR using only the integer/float operators and functions available in HxSL or PixelBlender).
None of the predefined filters or shaders in Flash that I can find seem to be able to do a XOR of two images (but again, am I missing something obvious? Can XOR be done with a combination of other filters).
I can find nothing like a XOR drawmode for drawing things onto other things (but that doesn't mean it doesn't exist! That would work too, if it exists!)
The only way I can find at the moment is a pixel-by-pixel loop over the image, but this takes a couple of seconds per image even on a fast machine, as opposed to filters, which I use for my other image processing operations, which are about a hundred times faster.
Is there any faster method?
Edit:
Playing around with this a bit more I found that removing the conditional and extra Vector access in the loop speeds it up by about 100ms on my machine.
Here's the previous XOR loop:
// Original Vector XOR code:
for (var i: int = 0; i < len; i++) {
// XOR.
result[i] = vec1[i] ^ vec2[i];
if (ignoreAlpha) {
// Force alpha of FF so we can see the result.
result[i] |= 0xFF000000;
}
}
Here is the updated XOR loop for the Vector solution:
if (ignoreAlpha) {
// Force alpha of FF so we can see the result.
alphaMask = 0xFF000000;
}
// Fewer Vector accessors makes it quicker:
for (var i: int = 0; i < len; i++) {
// XOR.
result[i] = alphaMask | (vec1[i] ^ vec2[i]);
}
Answer:
Here are the solutions that I've tested to XOR two images in Flash.
I found that the PixelBender solution is about 6-10 slower than doing it in straight ActionScript.
I don't know if it's because I have a slow algorithm or it's just the limits of trying to fake bitwise operations in PixelBender.
Results:
PixelBender: ~6500ms
BitmapData.getVector(): ~480-500ms
BitmapData.getPixel32(): ~1200ms
BitmapData.getPixels(): ~1200ms
The clear winner is use BitmapData.getVector() and then XOR the two streams of pixel data.
1. PixelBender solution
This is how I implemented the bitwise XOR in PixelBender, based on the formula given on Wikipedia: http://en.wikipedia.org/wiki/Bitwise_operation#Mathematical_equivalents
Here is a Gist of the final PBK: https://gist.github.com/Coridyn/67a0ff75afaa0163f673
On my machine running an XOR on two 3200x1400 images this takes about 6500-6700ms.
I first converted the formula to JavaScript to check that it was correct:
// Do it for each RGBA channel.
// Each channel is assumed to be 8bits.
function XOR(x, y){
var result = 0;
var bitCount = 8; // log2(x) + 1
for (var n = 0; n < bitCount; n++) {
var pow2 = pow(2, n);
var x1 = mod(floor(x / pow2), 2);
var y1 = mod(floor(y / pow2), 2);
var z1 = mod(x1 + y1, 2);
result += pow2 * z1;
}
console.log('XOR(%s, %s) = %s', x, y, result);
console.log('%s ^ %s = %s', x, y, (x ^ y));
return result;
}
// Split out these functions so it's
// easier to convert to PixelBender.
function mod(x, y){
return x % y;
}
function pow(x, y){
return Math.pow(x, y);
}
function floor(x){
return Math.floor(x);
}
Confirm that it's correct:
// Test the manual XOR is correct.
XOR(255, 85); // 170
XOR(170, 85); // 255
XOR(170, 170); // 0
Then I converted the JavaScript to PixelBender by unrolling the loop using a series of macros:
// Bitwise algorithm was adapted from the "mathematical equivalents" formula on Wikipedia:
// http://en.wikipedia.org/wiki/Bitwise_operation#Mathematical_equivalents
// Macro for 2^n (it needs to be done a lot).
#define POW2(n) pow(2.0, n)
// Slight optimisation for the zeroth case - 2^0 = 1 is redundant so remove it.
#define XOR_i_0(x, y) ( mod( mod(floor(x), 2.0) + mod(floor(y), 2.0), 2.0 ) )
// Calculations for a given "iteration".
#define XOR_i(x, y, i) ( POW2(i) * ( mod( mod(floor(x / POW2(i)), 2.0) + mod(floor(y / POW2(i)), 2.0), 2.0 ) ) )
// Flash doesn't support loops.
// Unroll the loop by defining macros that call the next macro in the sequence.
// Adapted from: http://www.simppa.fi/blog/category/pixelbender/
// http://www.simppa.fi/source/LoopMacros2.pbk
#define XOR_0(x, y) XOR_i_0(x, y)
#define XOR_1(x, y) XOR_i(x, y, 1.0) + XOR_0(x, y)
#define XOR_2(x, y) XOR_i(x, y, 2.0) + XOR_1(x, y)
#define XOR_3(x, y) XOR_i(x, y, 3.0) + XOR_2(x, y)
#define XOR_4(x, y) XOR_i(x, y, 4.0) + XOR_3(x, y)
#define XOR_5(x, y) XOR_i(x, y, 5.0) + XOR_4(x, y)
#define XOR_6(x, y) XOR_i(x, y, 6.0) + XOR_5(x, y)
#define XOR_7(x, y) XOR_i(x, y, 7.0) + XOR_6(x, y)
// Entry point for XOR function.
// This will calculate the XOR the current pixels.
#define XOR(x, y) XOR_7(x, y)
// PixelBender uses floats from 0.0 to 1.0 to represent 0 to 255
// but the bitwise operations above work on ints.
// These macros convert between float and int values.
#define FLOAT_TO_INT(x) float(x) * 255.0
#define INT_TO_FLOAT(x) float(x) / 255.0
XOR for each channel of the current pixel in the evaluatePixel function:
void evaluatePixel()
{
// Acquire the pixel values from both images at the current location.
float4 frontPixel = sampleNearest(inputImage, outCoord());
float4 backPixel = sampleNearest(diffImage, outCoord());
// Set up the output variable - RGBA.
pixel4 result = pixel4(0.0, 0.0, 0.0, 1.0);
// XOR each channel.
result.r = INT_TO_FLOAT ( XOR(FLOAT_TO_INT(frontPixel.r), FLOAT_TO_INT(backPixel.r)) );
result.g = INT_TO_FLOAT ( XOR(FLOAT_TO_INT(frontPixel.g), FLOAT_TO_INT(backPixel.g)) );
result.b = INT_TO_FLOAT ( XOR(FLOAT_TO_INT(frontPixel.b), FLOAT_TO_INT(backPixel.b)) );
// Return the result for this pixel.
dst = result;
}
ActionScript Solutions
2. BitmapData.getVector()
I found the fastest solution is to extract a Vector of pixels from the two images and perform the XOR in ActionScript.
For the same two 3200x1400 this takes about 480-500ms.
package diff
{
import flash.display.Bitmap;
import flash.display.DisplayObject;
import flash.display.IBitmapDrawable;
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
/**
* #author Coridyn
*/
public class BitDiff
{
/**
* Perform a binary diff between two images.
*
* Return the result as a Vector of uints (as used by BitmapData).
*
* #param image1
* #param image2
* #param ignoreAlpha
* #return
*/
public static function diffImages(image1: DisplayObject,
image2: DisplayObject,
ignoreAlpha: Boolean = true): Vector.<uint> {
// For simplicity get the smallest common width and height of the two images
// to perform the XOR.
var w: Number = Math.min(image1.width, image2.width);
var h: Number = Math.min(image1.height, image2.height);
var rect: Rectangle = new Rectangle(0, 0, w, h);
var vec1: Vector.<uint> = BitDiff.getVector(image1, rect);
var vec2: Vector.<uint> = BitDiff.getVector(image2, rect);
var resultVec: Vector.<uint> = BitDiff.diffVectors(vec1, vec2, ignoreAlpha);
return resultVec;
}
/**
* Extract a portion of an image as a Vector of uints.
*
* #param drawable
* #param rect
* #return
*/
public static function getVector(drawable: DisplayObject, rect: Rectangle): Vector.<uint> {
var data: BitmapData = BitDiff.getBitmapData(drawable);
var vec: Vector.<uint> = data.getVector(rect);
data.dispose();
return vec;
}
/**
* Perform a binary diff between two streams of pixel data.
*
* If `ignoreAlpha` is false then will not normalise the
* alpha to make sure the pixels are opaque.
*
* #param vec1
* #param vec2
* #param ignoreAlpha
* #return
*/
public static function diffVectors(vec1: Vector.<uint>,
vec2: Vector.<uint>,
ignoreAlpha: Boolean): Vector.<uint> {
var larger: Vector.<uint> = vec1;
if (vec1.length < vec2.length) {
larger = vec2;
}
var len: Number = Math.min(vec1.length, vec2.length),
result: Vector.<uint> = new Vector.<uint>(len, true);
var alphaMask = 0;
if (ignoreAlpha) {
// Force alpha of FF so we can see the result.
alphaMask = 0xFF000000;
}
// Assume same length.
for (var i: int = 0; i < len; i++) {
// XOR.
result[i] = alphaMask | (vec1[i] ^ vec2[i]);
}
if (vec1.length != vec2.length) {
// Splice the remaining items.
result = result.concat(larger.slice(len));
}
return result;
}
}
}
3. BitmapData.getPixel32()
Your current approach of looping over the BitmapData with BitmapData.getPixel32() gave a similar speed of about 1200ms:
for (var y: int = 0; y < h; y++) {
for (var x: int = 0; x < w; x++) {
sourcePixel = bd1.getPixel32(x, y);
resultPixel = sourcePixel ^ bd2.getPixel(x, y);
result.setPixel32(x, y, resultPixel);
}
}
4. BitmapData.getPixels()
My final test was to try iterating over two ByteArrays of pixel data (very similar to the Vector solution above). This implementation also took about 1200ms:
/**
* Extract a portion of an image as a Vector of uints.
*
* #param drawable
* #param rect
* #return
*/
public static function getByteArray(drawable: DisplayObject, rect: Rectangle): ByteArray {
var data: BitmapData = BitDiff.getBitmapData(drawable);
var pixels: ByteArray = data.getPixels(rect);
data.dispose();
return pixels;
}
/**
* Perform a binary diff between two streams of pixel data.
*
* If `ignoreAlpha` is false then will not normalise the
* alpha to make sure the pixels are opaque.
*
* #param ba1
* #param ba2
* #param ignoreAlpha
* #return
*/
public static function diffByteArrays(ba1: ByteArray,
ba2: ByteArray,
ignoreAlpha: Boolean): ByteArray {
// Reset position to start of array.
ba1.position = 0;
ba2.position = 0;
var larger: ByteArray = ba1;
if (ba1.bytesAvailable < ba2.bytesAvailable) {
larger = ba2;
}
var len: Number = Math.min(ba1.length / 4, ba2.length / 4),
result: ByteArray = new ByteArray();
// Assume same length.
var resultPixel:uint;
for (var i: uint = 0; i < len; i++) {
// XOR.
resultPixel = ba1.readUnsignedInt() ^ ba2.readUnsignedInt();
if (ignoreAlpha) {
// Force alpha of FF so we can see the result.
resultPixel |= 0xFF000000;
}
result.writeUnsignedInt(resultPixel);
}
// Seek back to the start.
result.position = 0;
return result;
}
There are a few possible options depending on what you want to achieve (e.g. is the XOR per channel or is it just any pixel that is non-black?).
There is the BitmapData.compare() method which can give you a lot of information about the two bitmaps. You could BitmapData.threshold() the input data before comparing.
Another option would be to use the draw method with the BlendMode.DIFFERENCE blend mode to draw your two images into the same BitmapData instance. That will show you the difference between the two images (equivalent to the Difference blending mode in Photoshop).
If you need to check if any pixel is non-black then you can try running a BitmapData.threshold first and then draw the result with the difference blend mode as above for the two images.
Are you doing this for image processing or something else like per-pixel hit detection?
To start with I'd have a look at BitmapData and see what is available to play with.

How to make a sliding menu in cocos2dx in c++ for IOS game

I want to make a sliding menu just like the level menu in which on one screen there will be 40 sprites labelled as level 1 level 2 respectively up to 40.
At the bottom right there will be another sprite with a arrow to which when I click it should slide to other screen and show the levels 41 to 80.Please provide me with a basic concept how to use it.I will be thankful to you.
Note: I am using Xcode and ony want solution in cocos2d-x using c++
This is the way I have done this in the past...I had a game with the option for the player to select multiple space ships, 4 per page, with back/forward arrows on each page as well.
Create a CCScene derived class.
Place all your menu items, including the control arrows for ALL pages on it. You will have to space all the items so the items for the first page are on the visible part of the screen and the next group is 100% off to the right, the third group is 200% off the right, etc.
The control buttons on the scene start an action to move the layer 100% to the left (if they move right) or 100% to the right (if they move left).
All of these are attached to a single "Menu", which is what the actions are applied against. If you want, you can put the menu into a layer (so it has background that moves). This is up to you.
In the example Scene below, I just used a simple menu.
MainScene.h
#ifndef __MainScene__
#define __MainScene__
#include "cocos2d.h"
using namespace cocos2d;
class MainScene : public CCScene
{
private:
// This class follows the "create"/"autorelease" pattern.
// Private constructor.
MainScene();
CCMenu* _menu;
bool _sliding;
void MenuCallback(CCObject* sender);
void PageLeft();
void PageRight();
void SlidingDone();
protected:
// This is protected so that derived classes can call it
// in their create methods.
bool init();
private:
void CreateMenu();
public:
static MainScene* create();
~MainScene();
virtual void onEnter();
virtual void onExit();
virtual void onEnterTransitionDidFinish();
virtual void onExitTransitionDidStart();
};
#endif /* defined(__MainScene__) */
MainScene.cpp
#include "MainScene.h"
#define ARROW_LEFT (-1)
#define ARROW_RIGHT (-2)
#define MENU_ITEMS_ACROSS 4
#define MENU_ITEMS_DOWN 5
#define MENU_ITEMS_PAGE (MENU_ITEMS_ACROSS*MENU_ITEMS_DOWN)
#define MENU_ITEMS_TOTAL 50
#define MENU_PAGES ((MENU_ITEMS_TOTAL/MENU_ITEMS_PAGE)+1)
#define MENU_FRACTION (ccp(0.8,0.8))
#define MENU_ANCHOR (ccp(0.5,0.5))
#define SLIDE_DURATION 1.0
MainScene::MainScene() :
_menu(NULL)
_sliding(false)
{
}
MainScene::~MainScene()
{
}
static CCPoint CalculatePosition(int itemNum)
{
CCSize scrSize = CCDirector::sharedDirector()->getWinSize();
float Xs = scrSize.width;
float Ys = scrSize.height;
int gRows = MENU_ITEMS_DOWN;
int gCols = MENU_ITEMS_ACROSS;
int gBins = gRows*gCols;
float Xb = MENU_FRACTION.x*Xs/gCols;
float Yb = MENU_FRACTION.y*Ys/gRows;
float Xa = MENU_ANCHOR.x * Xs;
float Ya = MENU_ANCHOR.y * Ys;
int page = itemNum / gBins;
int binCol = itemNum % gCols;
int binRow = (itemNum-page*gBins) / gCols;
float xPos = binCol * Xb + Xb/2 + Xa - MENU_FRACTION.x*Xs/2 + page * Xs;
float yPos = Ya - binRow*Yb - Yb/2 + MENU_FRACTION.y * Ys/2;
CCPoint pos = ccp(xPos,yPos);
return pos;
}
void MainScene::CreateMenu()
{
if(_menu == NULL)
{
CCSize scrSize = CCDirector::sharedDirector()->getWinSize();
_menu = CCMenu::create();
_menu->setPosition(ccp(0,0));
addChild(_menu);
CCMenuItemFont* pItem;
CCPoint position;
// Create the next/back menu items.
for(int page = 0; page < MENU_PAGES; page++)
{
// Create the Back/Forward buttons for the page.
// Back arrow if there is a previous page.
if(page > 0)
{
pItem = CCMenuItemFont::create("Back", this, menu_selector(MainScene::MenuCallback));
pItem->setTag(ARROW_LEFT);
position = ccp(page*scrSize.width + scrSize.width*0.1,scrSize.height*0.1);
pItem->setPosition(position);
pItem->setFontSize(35);
pItem->setFontName("Arial");
_menu->addChild(pItem);
}
if(page < (MENU_PAGES-1))
{
pItem = CCMenuItemFont::create("Next", this, menu_selector(MainScene::MenuCallback));
pItem->setTag(ARROW_RIGHT);
position = ccp(page*scrSize.width + scrSize.width*0.9,scrSize.height*0.1);
pItem->setPosition(position);
pItem->setFontSize(35);
pItem->setFontName("Arial");
_menu->addChild(pItem);
}
}
// Create the actual items
for(int idx = 0; idx < MENU_ITEMS_TOTAL; idx++)
{
char buffer[256];
sprintf(buffer,"Item #%d",idx);
pItem = CCMenuItemFont::create(buffer, this, menu_selector(MainScene::MenuCallback));
pItem->setFontSize(35);
pItem->setFontName("Arial");
pItem->setTag(idx);
position = CalculatePosition(idx);
pItem->setPosition(position);
_menu->addChild(pItem);
}
}
}
bool MainScene::init()
{
return true;
}
MainScene* MainScene::create()
{
MainScene *pRet = new MainScene();
if (pRet && pRet->init())
{
pRet->autorelease();
return pRet;
}
else
{
CC_SAFE_DELETE(pRet);
return NULL;
}
}
void MainScene::onEnter()
{
CCScene::onEnter();
CreateMenu();
}
void MainScene::onExit()
{
CCScene::onExit();
}
void MainScene::onEnterTransitionDidFinish()
{
CCScene::onEnterTransitionDidFinish();
}
void MainScene::onExitTransitionDidStart()
{
CCScene::onExitTransitionDidStart();
}
void MainScene::SlidingDone()
{
_sliding = false;
}
void MainScene::PageLeft()
{
if(_sliding)
return;
_sliding = true;
CCSize scrSize = CCDirector::sharedDirector()->getWinSize();
CCFiniteTimeAction* act1 = CCMoveBy::create(SLIDE_DURATION, ccp(scrSize.width,0));
CCFiniteTimeAction* act2 = CCCallFunc::create(this, callfunc_selector(MainScene::SlidingDone));
_menu->runAction(CCSequence::create(act1,act2,NULL));
}
void MainScene::PageRight()
{
if(_sliding)
return;
_sliding = true;
CCSize scrSize = CCDirector::sharedDirector()->getWinSize();
CCFiniteTimeAction* act1 = CCMoveBy::create(SLIDE_DURATION, ccp(-scrSize.width,0));
CCFiniteTimeAction* act2 = CCCallFunc::create(this, callfunc_selector(MainScene::SlidingDone));
_menu->runAction(CCSequence::create(act1,act2,NULL));
}
void MainScene::MenuCallback(CCObject* sender)
{
// This is a very contrived example
// for handling the menu items.
// -1 ==> Left Arrow
// -2 ==> Right Arrow
// Anything else is a selection
CCMenuItem* pMenuItem = (CCMenuItem*)sender;
switch(pMenuItem->getTag())
{
case ARROW_LEFT:
PageLeft();
break;
case ARROW_RIGHT:
PageRight();
break;
default:
CCLOG("Got Item %d Pressed",pMenuItem->getTag());
break;
}
}
Note The formulas for getting the items spread across several pages can be a little tricky. There is a notion of "Screen fraction", which is how much the grid of items takes up on the page. There is also the notion of "menu anchor", which where on the page you want the grid to be.
Some screen shots
or you can do it the modern way with less code!!
// you have to include this header to use the ui classes
#include "ui/CocosGUI.h"
using namespace ui;
#define COLS 4
#define ROWS 4
#define ITEMS_PER_PAGE (ROWS * COLS)
#define TOTAL_PAGES_NUM 10
#define MENU_PADDING (Vec2(0.8,0.8))
#define MENU_ANCHOR (Vec2(0.5,0.5))
static Vec2 calcPosition(int itemNum)
{
Size scrSize = Director::getInstance()->getWinSize();
float Xs = scrSize.width;
float Ys = scrSize.height;
float Xb = MENU_PADDING.x*Xs / COLS;
float Yb = MENU_PADDING.y*Ys / ROWS;
float Xa = MENU_ANCHOR.x * Xs;
float Ya = MENU_ANCHOR.y * Ys;
int page = itemNum / ITEMS_PER_PAGE;
int binCol = itemNum % COLS;
int binRow = (itemNum - page * ITEMS_PER_PAGE) / COLS;
float xPos = binCol * Xb + Xb / 2 + Xa - MENU_PADDING.x*Xs / 2 + page * Xs;
float yPos = Ya - binRow*Yb - Yb / 2 + MENU_PADDING.y * Ys / 2;
return Vec2(xPos, yPos);
}
//init method
// pageView is the container that will contain all pages
auto pageView = PageView::create();
pageView->setContentSize(winSize);
//if you want pages indicator just uncomment this
//pageView->setIndicatorEnabled(true);
//pageView->setIndicatorPosition(some position);
//pageView->setIndicatorSelectedIndexColor(some Color3B);
for (int i = 0; i < TOTAL_PAGES_NUM; i++) {
auto layout = Layout::create();
layout->setContentSize(winSize);
// give each page a different random color
int r = rand() % 200;
int g = rand() % 200;
int b = rand() % 200;
auto bg = LayerColor::create(Color4B(Color3B(r, g, b)), winSize.width, winSize.height);
layout->addChild(bg, 0);
// populate each single page with items (which are in this case labels)
for (int i = 0; i < ITEMS_PER_PAGE; i++) {
auto label = LabelTTF::create(StringUtils::format("item %i", (i + 1)), "Comic Sans MS", 15);
Vec2 pos = calcPosition(i);
label->setPosition(pos);
layout->addChild(label, 1);
}
pageView->addPage(layout);
}
this->addChild(pageView);
I’ve modified existing one and uploaded in github. Here is the link:
GitHub Link to SlidingMenu
You may find it helpful. You can directly add it into your game.