We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I have this code that draws a parametric line animation on the screen:
float t; int lines = 15;
void setup(){
size(500, 500);
}
void draw(){
background(0);
translate(width/2, height/2);
strokeWeight(5);
for(int i = 0; i < lines; i++){
stroke(255);
line(x1(t+1.5*i), y1(t+1.5*i), x2(t+1.5*i), y2(t+1.5*i));
}
t+=0.1;
}
float x1(float t){
return sin(t/10)*100;
}
float y1(float t){
return cos(t/10)*100;
}
float x2(float t){
return sin(t/20)*200;
}
float y2(float t){
return cos(t/20)*200;
}
I was wondering if I could use an ArrayList in order to store this parametric function and call it in the draw function? I would setup the for loop and the (x1, x2, y1, y2) functions in a class and then store that curve in index [0] of the array. I'm asking this, because I want to make two or three different functions that could be stored in indices [1] & [2] of the array so that a user could select or delete a certain curve via some key press event.
If that won't work I suppose I could still have a key press event in the draw function and setup multiple for loops for each function. If that's the case I'd ask if it's possible to set up a key press statement where you press a key and the function is drawn, then if you press the key again the function is deleted or stops drawing itself?
Answers
this
is a nice idea and would work
Got it. I just decided to go with a standard array:
Main
Class
Now I'm back to the issue of key pressing. I want to have it where the user can press the key '1' and the curve will start drawing, then if the user presses '1' again the curve will stop drawing. I imagine it'll be some combination of
keyPressed()
and a boolean value. I noticed you have to hold down the key when you use that function, though.keyPressed (te variable) might behave differently as it is based on OS and user keyboard configuration.
For your challenge, I'd use keyReleased(). Using a boolean value sounds perfect. You can add this value inside your class.
Kf
when you want the function graph to grow visibly, you can use the fact that draw() in itself loops automatically. 1 starts and stops it.
Also, you need a key to change this:
in my opinion use an int index variable and change its value on key
Alright, so this worked for 1 function, but for 2 it's not exactly doing what I want.
Main
Class
It works, but my logic isn't quite clever enough. I want each function to stay up with the others as long as the button has been pressed. So, if there are 4 functions and the user presses '1' '2' '3' '4' all 4 functions will be on the screen. And if the user then presses '3' again the function 3 disappears. Basically each will be independent of the others.
as said, just change
indexFunction
in this:functions[indexFunction].draw_function1();
??
it's much complicater than this, you need a different formula for each object from the class.
this is an example:
class State
Alright, so I definitely need to switch to an ArrayList first. but I see how it's a bit more complex.
The example should hopefully help. Thanks.
Sorry, I've never dealt with the extend method.
In my example does that mean I only need to write my x1,x2,y1,y2 functions in the base class and then can access in every other class by using extend?
I don't know
I guess so
extend is not a method, it is a keyword. I don't know exactly what it's called though. Maybe @GoToLoop will know?
In any case,
class B extends A{
means that B is a sublclass of A. Which means that all functions in A can also be used in B. Same for variables. Read about inheritance in Java for more info.https://forum.Processing.org/two/discussion/21321/change-method
I've implements parts of what's been suggested. Had to use some
abstract
methods to get it to work correctly. Here is the basic layout so far:I edited my above code. It works now, but I'm still working out how to get all functions to independently draw and stop drawing to the screen via pushing a number key. I'll try using
keyRelease()
again with a Boolean value.you are doing it wrong.
in your approach, the ArrayList holds only one member, not many.
maybe one of the gurus can shed a light here
this is wrong:
it should be independent classes:
the trick is although you have independent classes, they can all be in the same ArrayList since they all have the same base class Parametric
a link has been given to you by gotoloop
there you'll find a similar example:
but based on your approach:
@Chrisir To prevent your "@Override" from becoming a link, put a space between @ and Override.
While your example is right, I feel it is a bit incomplete - there's barely any point in making two classes for the same thing.
@PRouse what is your aim here? If it is indeed what I think, even despite @Chrsir's additions it wouldn't be quite okay.
Lord_of_the_Galaxy:
I fixed the @ Override issue thanks.
you also wrote:
that was merely an example as how to write the functions (post 8:37 am). Of course they must later hold different functions like the ai's in gotoloops example
Maybe the
extend
approach is too complicateinstead you could have a
switch
for function type and then store all into one classSorry, I'm still learning to get everything clean and concise with my code. Thanks for the input.
@Lord_of_the_Galaxy: As far as what I'm trying to do -- I was making a program where a user can independently press multiple number keys and get different parametric functions to draw on the screen, and then if they press the number again it stops drawing. I'm also going to allow the user to control the number of lines (just now implemented that), and I want the user to be able to pick from a few different colors for each set of lines.
Based on Wikipedia's definition of "function"
I would say that all you really need is an interface
Function
.@Chrisir I suppose that you're in the right, our OP's approach has probably been wrong in the first place.
@Lord_of_the_Galaxy Yea, I know what a function is.
I know my approach is likely wrong, as I having to pick this up as I go. What's needed first is to get something that works, and so far it's working correctly. I'll clean it up as I go, which is why I appreciate the input.
I never said you didn't know what a function is. I always assume the worst, so in case someone doesn't know, for them it's there. In any case, the point was that a single interface is all you should be using. Try it, it looks a lot better.
@PRouse
Can you add a second piece of code showing what a second parametric function will look like?
Now:
I will manage the keyEvent at the draw level. You are setting up an array that has your functions. Based on keyEvents, you choose what array to show. I don't understand your delete events though. Do you want to delete a parametric function or lines drawn when you have selected one of those parametric functions? I would suggest instead of deleting, you can hide. I will need to understand your concept before going further.
Here is my attempted to show what you can do with your code. As soon as you clarify some of my doubts, I could show you a better approach of doing this, even maybe using interfaces.
Kf
I tried some of the ideas suggested. The switch doesn't seem to be working, when I press 1 or 2 nothing shows up. Also the interface Function throws an error when I try to set it up.
Error: The member interface Function can only be defined inside a top-level class or interface or in a static context.
Apparently I'm confusing everyone about what I want done, so here's the code that does exactly that (it's probably not clean and concise, but it works):
I also wanted to ask, with the
text()
, can you add a variable in? For example, if I wanted to print the number of lines via the numLines variable.text(""+numLines ,posX,posY);
Kf
Notice my last code in my post had an error due to the forum formatting. Make sure the code reads "@Override" as I had to add a space so it wasn't changed by the forum formatting. Or you can remove those lines. There are two of them.
One needs to understand better the function of your code before trying to design the class layout.
You have two features in your code:
In concept you only need a class called function.
Notice that the difference between function 1 and 2 is the direction of the parametric calculation. In concept you will have:
class fun{ maxLines.....make it int final parametric values... the x()'s and y()'s functions number of lines dir....either +1 or -1 color visibleStatus...Boolean void drawLine() }
In setup():
Add functions to your array. A function is defined by nLines,dir,visible status,color
In draw():
You traverse your array and show those lines with the visible flag set to true.
In key Event:
1. Increase decrease the number of lines (all the objects in the array or just the one being shown?)
2. Toggle what lines to show in the array
However, this approach only works if you function uses only x1,y1,x2,y2 definitions and you want to create multiples objects with the same values.
If you want to include some other parametric equation then you need to modify the function above. In the constructor, you need to define those values as well. Easy and done. Another approach (you don't have to) is to use OOP.
One parent class defines what you need. Any subclasses re-defines what is defined in the parent class. Now the parent class can be a class or an interface. But it really depends on your requirement. If you provide a better description of what a parametric line is in your context, or how many models you want to implement, then one could suggest if you should stick to a single class or if it is worth it to migrate to using extended classes. From what you show in your last code, I will stick to a simple class as I discussed above.
Kf
You're correct, though I want one last feature:
I'll have a list of colors to pick from, and set up small squares somewhere on the screen that show the current color for each set (those squares will pop up and disappear along with each function).
As far as increasing and decreasing the lines, I'll stick with all the functions.
I'm only using x1, y1, x2, y2, but I am going to use additions of sines and cosines to give the lines a more unique path. I also have 8 different functions, each unique. I was just using the current two while getting the program to work. It still seem's easier to set all 8 functions up in one extended class, since they all use the same variables (t and lines) and the x1, y1, x2, y2, and use the parent class to define x1, y1, x2, y2, and the variables used. I don't quite understand how interfaces work and what makes them better to use, so I think I'll stick with the abstract class.
Or you could try using the QScript library by @quark.
http://www.lagers.org.uk/qscript/index.html
I don't think you need to use extended or abstract classes. When you build an object of your design, you only need to define:
You define all these values in the object constructor and then call the object's
display()
function (equivalent to yourdrawFunction1();
) in draw.Then you manage the number of lines, visible curves and their color in the main draw() function.
More about interfaces: https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html
At the bottom on the left menu there is also a discussion about abstract classes.
About the buttons, you can use something like the following class. You need to adapt it to manage color after a click action.
Kf
So, I changed things up a bit. Instead of having different functions I just made a bunch of equations that can be used in sets. I tried using the constructor to pass arguments and do the bulk in the Parametric class, but there's a few problems. It skips through the number of lines too quickly, which is because it's doing it all at once in
draw()
, but I need to use thekeyPressed()
method for selection. It's the same with picking the set of equations and dt. I also need to figure out how to use my flags correctly in order to have one function show up at a time, starting with zero. And translate doesn't seem to be working correctly. There are lines showing up at the corners of the screen.This code works exactly how I want it to, other than adding color selection. However, I don't know if it's good practice to write it this way.
To be true, it's certainly not good practice to write it in this way. It's really difficult to se what you're trying to do here. Are you trying to graph some functions? In fact, if I were to guess, there's completely no point in using classes the way you're doing it.
@PRouse -- beautiful animation once you turn all the segments on, increase the line count to 25, speed up the steps, and then cycle through the sets.
@Lord_of_the_Galaxy
Nope, not trying to graph anything. If that were the case I'd need to actually draw a graph with some sort of coordinate system, my code has nothing of the sort in it. Just trying to do some neat mathematical animations and allowing the user some input as @jeremydouglass pointed out (thanks by the way).
I was using classes because that was suggested as a better method, and it allows me to break things up into tabs instead of just writing 221 lines of code straight. I'm not sure if you can see the whole discussion thread or not, but I've listed multiple times what I'm attempting to do with the code. The last code I gave in my previous post works nicely and does what I want other than color options (which I'm working on). But I guess it is, as you say, not good practice in the way it is written. My apologies, I'm still learning...which is why I've appreciated all the advice up to now.
Finished it. Everything surprisingly works well. Thanks @kfrajer for suggesting the button class example, it worked out nicely.
Actually, you don't need to use classes to break up your code into tabs L-)
Yea, I guess I just thought classes would make it a little more organized. I'm working on coding it correctly, as I know you're supposed to pass all variables via the constructor and do the bulk in those classes. I do too much in
setup()
anddraw()
and should not really be passing variables to the methods inside the classes.I suppose I could do nothing but functions, but I feel like that would be unorganized.
@Prouse -- nice sketch results. Reviewing your code I notice that you have hard-coded parameter arguments as special cases everywhere.
My main suggestion for improvement would be, given that your parametrics all take the form
sin|cos(x/div1)*mult1 + sin|cos(x/div2)*mult2
you should simplify your equation class a lot and then get rid of all the special cases for equations that you have everywhere.Here is an example of an Equation object -- it stores its arguments and returns the two wave components when you call Object.f(x):
Here is a global array of 4 sets of 4 equations each:
...and here is setup() code that defines each of your Equations using their parameters:
The final step is to rethink the parametric drawing. This could be a Parametric class object or it could be a function. You could pass it a single equation (
eqSets[0][0]
) or pass it a set of equations(eqSets[0]
). In any case, the object doesn't contain multiple sets of special rules for specifically named equation sets -- it treats all equations equally, something like (untested):Beautifully done, @jeremydouglass
Thank you @jeremydouglass, that helped cut down on lines needed quite a bit. I cut down some lines a few other places too. I think this is formatted a little better.
A few problems though:
1) The key and mouse events I call to
draw()
are looping through to the end or beginning instead of going through one at a time. Is there a way to fix this, or do I need to do all mouse and key events outside of the class?2) Even through I initially pass the color white for the buttons, when they become visible the fill is still black for all of them.
3) To print out the number of lines, the current set of equations in use, and the speed of the lines, I need the variables for those in the
text()
functions. So, I need a way to pass those from the Parametric class where they are updated.Oh dear. Your code is so damn repetitive. @jeremydouglass may help set it right.
@Lord_of_the_Galaxy
Not sure what I did to piss you off my Lord, but I apologize. I'd rather get some suggestions or advice, but if insults are your thing...have at it I guess.
I'm not exactly pissed off, just commenting that despite being given an example, you resort to not using arrays. If you felt insulted, my apologies.
Lines 159-178 can be replaced with this -
lines 214-234 can be replaced by -
cols[counter-1]
, and at the top of the program, declare the array and initialise it with the required values, which I hope you know how to do, and thus leave to you.And in lines 183-202 do you notice how each of the four conditions check if
key==CODED
? That means that you can use anif(key==CODED){
as on outer condition for all inner conditions at once.This is much smaller, and I certainly wouldn't expect a beginner to set it, but there's nothing wrong in learning. So lines 264-267 can be replaced with
return (mouseX > x && mouseX < (x+w) && mouseY > y && mouseY < (y+h));
. The outer brackets exist purely to help one see it properly.