We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi , Im having a problem with objects (Tiles) - I set where a bunch of Tiles appear on the canvass and if the mouse cursor is over one of the Tiles it enlarges and plays a video. All this is working fine but I would like a way to say - if mouse cursor over object - draw this object last so that it is drawn over the other objects (effectively masking them out as it enlarges).
I had seen this; http://www.openprocessing.org/sketch/50914 - about drawing stack order.
This example is nearly exactly what I want to do but the problem is I still need to be able to set exactly where these objects appear on the canvass so I can't create them in a if statement or loop - they need to be set individually. Is there a way to re order when they are run though draw when the mouse hovers over them?
I had tried creating a discussion before but unfortunately I managed to put it in the wrong category so am re posting this here.
Code below - and thanks for the help!
import processing.video.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;
Minim minim;
AudioSample sample;
Tile[]Tiles = new Tile[10];
void setup() {
fullScreen(2);
//noCursor();
imageMode(CENTER);
minim = new Minim(this);
for (int i = 0; i< 10; i++){
Tiles[i]= new Tile(this);
Tiles[i].setMovie("TORCH_2_1.mov");
Tiles[i].setAudio(minim, "Paper Rustle_1.mp3");
}
}
void draw() {
background(0);
Tiles[0].presentTile(200, 200);
Tiles[1].presentTile(225, 200);
Tiles[2].presentTile(250, 200);
Tiles[3].presentTile(275, 200);
Tiles[4].presentTile(300, 200);
Tiles[5].presentTile(325, 200);
}
class Tile {
PApplet app;
Movie movie = null;
AudioSample sample = null;
boolean overBox = false;
boolean canTrigger = true;
float boxMax = 100;
float boxMin = 25;
int boxSize;
Tile(PApplet papp) {
app = papp;
boxSize = 25;
}
void setMovie(String fname) {
movie = new Movie(app, fname);
movie.loop();
movie.pause();
}
void setAudio(Minim m, String fname) {
sample = m.loadSample(fname, 512);
}
void isOver(float x, float y) {
overBox = (mouseX > x-(boxSize/2) && mouseX < x +(boxSize/2) &&
mouseY > y-(boxSize/2) && mouseY < y+(boxSize/2));
}
void presentTile(float bx, float by) {
isOver(bx, by);
if (movie != null) {
if (movie.available() == true)
movie.read();
if (overBox && (boxSize < boxMax)) {
image(movie, bx, by, boxSize++, boxSize++);
movie.loop();
}
if (!overBox && boxSize > boxMin ) {
image(movie, bx, by, boxSize-=1, boxSize-=1);
movie.pause();
}
image(movie, bx, by, boxSize, boxSize);
}
if (sample != null) {
if (canTrigger && overBox) {
sample.trigger();
canTrigger = false;
}
if (!overBox) {
sample.stop();
canTrigger = true;
}
}
}
}
Answers
Change line 41 to
class Tile implements Comparable<Tile> {
Add the following method to the Tile class
Change the draw to
Finally add the this import statement with the others
import java.util.*;
This will sort the tiles from smallest to largest inside the array then when you draw them the largest will be drawn last.
Thanks so much for getting back to me - this doesn't seem to be working for me. It runs but only the last tile is working correctly (expanding/playing).
It could be because I have not implemented this function properly?
Unfortunately I don't understand this part v well - do I need to swap out the "?" Im unsure what the "?" denotes.
Thanks again for the help!
Ternary conditional operator: https://Processing.org/reference/conditional.html
A more simplified compareTo():
Thanks for clarifying that - makes more sense now and certainly helps when I'm looking at other examples!
Its still not working correctly for me. This may be because I have not explained what I'm trying to do properly. The code I included in my first post was working fine except I wanted the active tile (the one that the mouse was over) to appear on top of the other tiles in its vicinity as its enlarging. I thought that the best solution would be to dynamically change the draw order so that the active tile would always be drawn last and therefore not be obscured .
This image below is what I'm trying to avoid - as the 4th tile enlarges it obscures the 3rd tile as that tile runs through draw 1st this is correct. But the 5th tile is not obscured as it runs through draw after the 4th. So it looks like its floating on top of the 4th tile.
Do I perhaps need to write another function that links the "Arrays.sort(Tiles);" to the "overBox" function?
Thanks again for your help guys - and your patience!
The problem is that the position of the Tile is determined by its position in the array. The Tile class should have fields to define the position of the Tile it SHOULD NOT be dependent on the index value in the array.
In your previous post I provided code that did this which you accepted at the time but have not used.
The tile array should define the ORDER they are drawn not the POSITION of the tile.
I think you will find that this works though you may need to tweak it a little
OK - thanks quark. This below is how my code looks at the mo - perhaps I have implemented your code wrongly? This is only allowing the last tile to be fully activated and also the other tiles seem to still be drawn in the original order.
Eventually i want to have a lot of tiles in a particular pattern so I still need to be able to set the location on the canvass of each tile. Thats why i have the arguments in the presentTile set to the bx,by. But If I'm following what your suggesting I need a function that places the tiles on the canvass then another that sets the draw order of the tiles in the array? But I can't use the array to set the locations?
Thanks again!
Sorry quark - I sent that last comment before receiving your most recent one - just looking at that code now.
The point is that each tile knows WHERE it should be drawn and the array knows WHEN it should be drawn.
ahhh ok - I see what u mean. So we have stated where the tile is with presentTile function on the individual tiles but the array is used in draw to sort all the tiles? I didn't realise i could use the array and still call the individual tiles that were in side the array.
I nearly have this working - I have taken your code and tried to alter it to fit my needs. The tiles are presented fine and the code runs. But something is effecting the playback of the tiles.. The sound and video is no longer playing smoothly and also the video/sound seems to be activated for all the tiles at once. Also - the tiles no longer enlarge to the maximum value - something is stopping this and I can't work out what. However - the tiles do enlarge partially and I can see that they do now cover the other tiles which is great. My current code below;
Thanks for the help!
There are serious problems with your code and we still have the problem that the presentMethod defines where the movie is shown. Looking back at my last post I noticed a bug in tbe peresentMethod so I have corrected it and the code is shown below.
Please run this code and if it doesn't do what you want then explain what is wrong.
The sorting of the array works great now - thanks. The only issue I now have is working out how to set the individual locations of the tiles. I understand in line 22 we are setting where the tiles are drawn and sending these arguments to the tile constructor but I can only apply an argument to the entire array here [i] instead of say - set tile[1] here and tile [2] here etc. How would I set the individual locations of the tiles in the array now if say i wanted one to be at coordinates 400,500 and another at 250,700 etc etc? Eventually i want to have a large number of these tiles in a particular pattern.
Thanks again for the help, its really been mega helpful!
The easy way is simply to change the position of the Tile. In the Tile class the attributes cx, cy controls where the tile is to be stored. We can do this simply by adding a method to the class like this
Put this method inside the class, line 61 would do it.
Then you can use something like
tile[1].setPosition(333,444);
There is only one issue and that is the order of the tiles in the array will change with the sort. In other words if we have a tile A at index position [1] in the array it will not always be at [1] due to the sorting. Is that a problem?
I don't think that should be a problem as all the tiles are the same - as long as one tile in the array is always at said location it should appear fine right? I am going to have a go at adding that function now and testing it out. would i place the
tile[1].setPosition(333,444); tile[2].setPosition(222,111); etc
in to draw as well?
So this is what I have so far;
I have set the location of all the tiles individually which has worked, unfortunately only the last tile in the array [9] is activating properly. The others are not enlarging or playing back correctly and I can't quite work out why..
Thanks
Change the setup and draw methods to
Since each tile knows where to display itself you don't need to set the position everyt time the sort method will swap the positions in the array so that the largest is in position [] so drawn last over the others. Remember the array is ONLY used to control the order the tiles are drawn NOT the position it is shown
ahhh yes! perfect thanks v much. I had tried placing the setPosition in setup but I think i must have got my syntax in a muddle - thanks very much for this help, its all working as I had intended now.
Great news :)