I created a screensaver that bounces around the screen. I tried to fit original the code into OOP (which I'm terrible at) so that I could have multiple versions of it bouncing around. Instead, I'm getting one instance travelling at an unusually fast speed.
How can I get instance1, instance2 and instance3 to be seperate instead of combining into one?
Notes:
In the class screenSavers, C stands for constructor parameter to differentiate from the original variables at the top. CS stands for class-specific to avoid confusion with the original variables at the top. (yes, it's confusing. I don't know why I did that)
GIANT WALL OF CODE ALERT
import java.lang.Math;
//defining dimensions and initial coords for the laptop frame
float frameW = 120;
float frameH = frameW * 3.0/4.0;
float frameX = random(frameW * 2, width);
float frameY = random(frameW * 2, height);
//defining variables are used in the movement of the laptop
float xSpeed = random(frameW / 50,frameH / 15);
float ySpeed = random(2,5);
boolean moveLeft = false;
boolean moveUp = false;
//defining the colours used in the program, as well as the alpha and stroke widths
int alpha = 255;
color baseColor = color(random(100, 255), random(100, 255), random(100, 255), alpha);
color accentColor = color(random(100, 255), random(100, 255), random(100, 255), alpha);
color baseColorAlpha;
color accentColorAlpha;
color bgColor = 0;
color outline = 255;
int outerCircleWeight = 5;
int laptopStrokeWeight = 1;
//initial states of little ellipses on the screen
float startingPoint = 7.5;
float leftDotRaise = 0;
boolean leftDown = false;
float centerDotRaise = 0;
boolean centerDown = false;
float rightDotRaise = 0;
boolean rightDown = false;
//variable for the radian at which the circles outside the laptop are at
float circleOrbit;
//variable for roundness of any initially circular shapes (ellipses, orbits, etc)
float specialRadii = 200;
//square-ification button
int buttonX = 200;
int buttonY = 200;
boolean buttonState = true;
int buttonTextSize = 30;
String offMessage = "Revert";
String onMessage = "Squarify";
String buttonMessage = onMessage;
public class screenSavers {
float frameWCS;
float xSpeedCS;
float ySpeedCS;
boolean moveLeftCS;
boolean moveUpCS;
int alphaCS;
color baseColorCS;
color accentColorCS;
color bgColorCS;
color outlineCS;
int outerCircleWeightCS;
int laptopStrokeWeightCS;
float startingPointCS;
float leftDotRaiseCS;
boolean leftDownCS;
float centerDotRaiseCS;
boolean centerDownCS;
float rightDotRaiseCS;
boolean rightDownCS;
float specialRadiiCS;
int buttonXCS;
int buttonYCS;
boolean buttonStateCS;
int buttonTextSizeCS;
String offMessageCS;
String onMessageCS;
String buttonMessageCS;
float circleOrbitCS;
public screenSavers (float frameWC, float xSpeedC, float ySpeedC, boolean moveLeftC, boolean moveUpC, int alphaC, color bgColorC, color outlineC, int outerCircleWeightC, int laptopStrokeWeightC, float startingPointC, float leftDotRaiseC, boolean leftDownC, float centerDotRaiseC, boolean centerDownC, float rightDotRaiseC, boolean rightDownC, float specialRadiiC, int buttonXC, int buttonYC, boolean buttonStateC, int buttonTextSizeC, String offMessageC, String onMessageC, String buttonMessageC, float circleOrbitC){
frameWCS = frameWC;
xSpeedCS = xSpeedC;
ySpeedCS = ySpeedC;
moveLeftCS = moveLeftC;
moveUpCS = moveUpC;
alphaCS = alphaC;
bgColorCS = bgColorC;
outlineCS = outlineC;
outerCircleWeightCS = outerCircleWeightC;
laptopStrokeWeightCS = laptopStrokeWeightC;
startingPointCS = startingPointC;
leftDotRaiseCS = leftDotRaiseC;
leftDownCS = leftDownC;
centerDotRaiseCS = centerDotRaiseC;
centerDownCS = centerDownC;
rightDotRaiseCS = rightDotRaiseC;
rightDownCS = rightDownC;
specialRadiiCS = specialRadiiC;
buttonXCS = buttonXC;
buttonYCS = buttonYC;
buttonStateCS = buttonStateC;
buttonTextSizeCS = buttonTextSizeC;
offMessageCS = offMessageC;
onMessageCS = onMessageC;
buttonMessageCS = buttonMessageC;
circleOrbitCS = circleOrbitC;
}
public void main(String[] args){
}
public void updateAlpha(){
/*
updates alpha versions of color variables that account for the alpha of the color, we have to put this
so that it updates every frame, otherwise the transparency will only update with every bounce. This way
the color updates with each bounce but the transparency constantly updates every frame (or 60 times per second)
*/
baseColorAlpha = color(red(baseColor),green(baseColor),blue(baseColor), alpha);
accentColorAlpha = color(red(accentColor),green(accentColor),blue(accentColor), alpha);
/*
transparency of objects changes with X position of the mouse, 1st quarter of the screen
= 25% brightness, 2nd quarter = 50%, 3rd quarter = 75%, 4th quarter = 100%
*/
if (mouseX < width / 3){
alpha = 75;
} else
if (mouseX > width / 3 && mouseX < 2 * width / 3) {
alpha = 150;
} else
if (mouseX > width * 2 / 3 && mouseX < width){
alpha = 255;
}
}
void resetBackground(){
//reset background to prevent copies of the laptop from generating
background(bgColor);
//set outline color
stroke(outline);
fill(baseColorAlpha);
}
void updateRadii (){
//changing radii of shapes based on button
if (buttonStateCS == true){
specialRadiiCS = 2 * frameW;
} else {
specialRadiiCS = 0;
}
}
void generateComputer(){
//making the frame
rect(frameX, frameY, frameW, frameH);
//making the screen
fill(accentColorAlpha);
rect(frameX, frameY, frameW - frameW / 5, frameH - frameH * 4.0/15.0);
//switching back to the base color for the moving ellipses on the screen
fill(baseColorAlpha);
//creating the laptop keyboard
fill(accentColorAlpha);
beginShape();
vertex(frameX - frameW / 2, frameY + frameH / 2);
vertex(frameX - (frameW / 2 + 15), frameY + frameH / 2 + 15);
vertex(frameX + frameW / 2 + 15, frameY + frameH / 2 + 15);
vertex(frameX + frameW / 2, frameY + frameH / 2);
endShape();
}
void dots(){
rect(frameX - frameW / 5,frameY + leftDotRaise + startingPoint,frameH / 5,frameH / 5,specialRadiiCS);
//moving the dots
if (leftDotRaise >= frameH * (11.0 / 75.0)){
leftDown = false;
} else
if (leftDotRaise <= frameH * (-11.0 / 75.0)){
leftDown = true;
}
if (leftDown == true){
leftDotRaise += frameH / 75;
} else if (leftDown == false){
leftDotRaise -= frameH / 75;
}
rect(frameX,frameY + centerDotRaise, frameH / 5, frameH / 5,specialRadiiCS);
if (centerDotRaise >= frameH * (11.0 / 75.0)){
centerDown = false;
} else
if (centerDotRaise <= frameH * (-11.0 / 75.0)){
centerDown = true;
}
if (centerDown == true){
centerDotRaise += frameH / 75;
} else if (centerDown == false){
centerDotRaise -= frameH / 75;
}
rect(frameX + frameW / 5,frameY + rightDotRaise - startingPoint,frameH / 5,frameH / 5,specialRadiiCS);
if (rightDotRaise >= frameH * (11.0 / 75.0)){
rightDown = false;
} else
if (rightDotRaise <= frameH * (-11.0 / 75.0)){
rightDown = true;
}
if (rightDown == true){
rightDotRaise += frameH / 75;
} else if (rightDown == false){
rightDotRaise -= frameH / 75;
}
startingPoint = 0;
}
void generateOrbitals(){
//creating and animated the outer rotating circles
pushMatrix();
translate(frameX, frameY);
rotate(circleOrbitCS);
translate(frameW * 1.5, frameH / -10);
circleOrbitCS += 0.01;
rect(0, 0, frameW / 2, frameW / 2, specialRadiiCS);
popMatrix();
pushMatrix();
translate(frameX, frameY);
rotate(circleOrbitCS);
translate(frameW * -1.5, frameH / 10);
circleOrbitCS += 0.01;
rect(0, 0, frameW / 2, frameW / 2, specialRadiiCS);
popMatrix();
pushMatrix();
translate(frameX, frameY);
rotate(circleOrbitCS);
translate(frameH / 10, frameW * 1.5);
circleOrbit += 0.01;
rect(0, 0, frameW / 2, frameW / 2, specialRadiiCS);
popMatrix();
pushMatrix();
translate(frameX, frameY);
rotate(circleOrbit);
translate(frameH / -10, frameW * -1.5);
circleOrbit += 0.01;
rect(0, 0, frameW / 2,frameW / 2, specialRadiiCS);
popMatrix();
}
void generateOuterCircle(){
noFill();
stroke(accentColor);
strokeWeight(outerCircleWeight);
rect(frameX, frameY, frameW * 4, frameW * 4,specialRadii);
strokeWeight(laptopStrokeWeight);
}
void bounce(){
if (frameX + 2 * frameW > width) {
moveLeft = true;
baseColor = color(random(50, 255), random(50, 255), random(50, 255),alpha);
accentColor = color(random(50, 255), random(50, 255), random(50, 255),alpha);
} else if (frameX - 2 * frameW < 0) {
moveLeft = false;
baseColor = color(random(50, 255), random(50, 255), random(50, 255),alpha);
accentColor = color(random(50, 255), random(50, 255), random(50, 255),alpha);
}
if (frameY + 8.0/3.0 * frameH > height) {
moveUp = true;
baseColor = color(random(50, 255), random(50, 255), random(50, 255),alpha);
accentColor = color(random(50, 255), random(50, 255), random(50, 255),alpha);
} else if (frameY - 8.0/3.0 * frameH < 0) {
moveUp = false;
baseColor = color(random(50, 255), random(50, 255), random(50, 255),alpha);
accentColor = color(random(50, 255), random(50, 255), random(50, 255),alpha);
}
if (moveLeft == true) {
xSpeed = abs(xSpeed) * -1;
} else {
xSpeed = abs(xSpeed);
}
if (moveUp == true) {
ySpeed = abs(ySpeed) * -1;
} else {
ySpeed = abs(ySpeed);
}
}
void updateCoords(){
//update coords
println("Screensaver Icon is currently at (" + frameX + ", " + frameY + ')');
}
void generateSquareButton(){
//square-ification button
fill(accentColor);
rect(buttonXCS,buttonYCS, 200, 200, specialRadiiCS);
fill(255);
textSize(buttonTextSizeCS);
text(buttonMessageCS,buttonXCS,buttonYCS+5);
}
void alignShapes(){
//letting the program know that we are referencing X and Y coords of a rectangle or text box by its center
rectMode(CENTER);
textAlign(CENTER);
}
void testForButton(){
//check if the mouse was pressed at the button's coordinates
if (mouseX > buttonXCS - 100 && mouseY > buttonYCS - 100 && mouseX < buttonXCS + 50 && mouseY < buttonYCS + 50){
//if the button is on, turn it off
if (buttonStateCS == true){
buttonStateCS = false;
buttonMessageCS = offMessageCS;
} else
//if the button is off, turn it on
if (buttonStateCS == false){
buttonStateCS = true;
buttonMessageCS = onMessageCS;
}
}
}
void move(){
frameX += xSpeed;
frameY += ySpeed;
}
void display(){
updateAlpha();
resetBackground();
updateRadii();
generateComputer();
dots();
generateOrbitals();
generateOuterCircle();
bounce();
move();
updateCoords();
generateSquareButton();
}
}
//creating the first instance of the screensaver as an object
screenSavers instance1 = new screenSavers(frameW,xSpeed,ySpeed,moveLeft,moveUp,alpha,bgColor,outline,outerCircleWeight,laptopStrokeWeight,startingPoint,leftDotRaise,leftDown,centerDotRaise, centerDown, rightDotRaise, rightDown, specialRadii, buttonX, buttonY, buttonState, buttonTextSize, offMessage, onMessage, buttonMessage,circleOrbit);
//creating the second instance of the screensaver as an object
screenSavers instance2 = new screenSavers(frameW,xSpeed,ySpeed,moveLeft,moveUp,alpha,bgColor,outline,outerCircleWeight,laptopStrokeWeight,startingPoint,leftDotRaise,leftDown,centerDotRaise, centerDown, rightDotRaise, rightDown, specialRadii, buttonX, buttonY, buttonState, buttonTextSize, offMessage, onMessage, buttonMessage,circleOrbit);
//creating the third instance of the screensaver as an object
screenSavers instance3 = new screenSavers(frameW,xSpeed,ySpeed,moveLeft,moveUp,alpha,bgColor,outline,outerCircleWeight,laptopStrokeWeight,startingPoint,leftDotRaise,leftDown,centerDotRaise, centerDown, rightDotRaise, rightDown, specialRadii, buttonX, buttonY, buttonState, buttonTextSize, offMessage, onMessage, buttonMessage,circleOrbit);
//setup loop, runs ONCE
void setup() {
/*note: to see the console update the X and Y, comment out fullScreen();
and un-comment size(1000,1000); */
//enters fullscreen, regardless of device resolution
fullScreen();
//uncomment this for seeing coords updated
//size(1000,1000);
//makes the framerate go from 24 to a smoother 60 frames. If I don't add this your eyes will hurt
frameRate(60);
instance1.alignShapes();
instance2.alignShapes();
instance3.alignShapes();
}
void draw() {
instance1.display();
instance2.display();
instance3.display();
}
//////////////////////////////////////////////////////////////////
//do something when mouse is pressed
void mousePressed(){
instance1.testForButton();
instance2.testForButton();
instance3.testForButton();
}```
Right now you initialize all 3 instances with the exact same properties. They are only "combined" because you made them the same. You should identify what you want to be different between them, and pass in different properties.
Other notes:
Why does screenSavers have a main() function? Delete it
Please rename it to ScreenSaver.
Do not distinguish using C vs CS. Just name them the same. But use the this keyword to distinguish the class vars. example: this.frameW = frameW;
Use proper indentation with if statements.
Found it a few days later by the way, I was looking for the this keyword
I would like to change the fill colour of an object over time. Is there a way to change the fill colour of an object after X frames?
I am learning about constructors, and I am thinking that in the code's updateParticle function, after this.age counts to 'X', the fill colour of the ellipse could change.
'''
function Particle(x, y, xSpeed, ySpeed, size, colour) {
this.x = x;
this.y = y;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.size = size;
this.colour = colour;
this.age = 0;
this.drawParticle = function() {
fill(this.colour);
noStroke();
ellipse(this.x, this.y, this.size);
}
this.updateParticle = function() {
this.x += this.xSpeed;
this.y += this.ySpeed;
this.age++;
}
}
function Emitter(x, y, xSpeed, ySpeed, size, colour) {
this.x = x;
this.y = y;
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.size = size;
this.colour = colour;
this.particles = [];
this.startParticles = [];
this.lifetime = 0;
this.addParticle = function() {
var p = new Particle(random(this.x - 10, this.x + 10),
random(this.y - 10, this.y + 10),
random(this.xSpeed - 0.4, this.xSpeed + 0.4),
random(this.ySpeed - 5, this.ySpeed - 1),
random(this.size - 4, this.size + 40),
this.colour);
return p;
}
this.startEmitter = function(startParticles, lifetime) {
this.startParticles = startParticles;
this.lifetime = lifetime;
for (var i = 0; i < startParticles; i++) {
this.particles.push(this.addParticle());
}
}
this.updateParticles = function() {
var deadParticles = 0
for (var i = this.particles.length - 1; i >= 0; i--) {
this.particles[i].drawParticle();
this.particles[i].updateParticle();
if (this.particles[i].age > random(0, this.lifetime)) {
this.particles.splice(i, 1);
deadParticles++;
}
}
if (deadParticles > 0) {
for (var i = 0; i < deadParticles; i++) {
this.particles.push(this.addParticle());
}
}
}
}
var emit;
function setup() {
createCanvas(800, 600);
emit = new Emitter(width / 2, height - 100, 0, -1, 10, color(200, 0, 200, 50));
emit.startEmitter(600, 4000);
}
function draw() {
background(200);
emit.updateParticles();
}
'''
Well you could just:
if(frameCount % 30 == 0){ // % 30 is the remainder of num / 30, so 4 % 3 = 1, since 3 / 3 = 0 And 4 / 3 = 3.33
fill("lime") // these are just preset colors in p5.js AND css lime == rgb(0,255,0)
} else {
fill('darkred')
}
or you could also do it with for example a switch statement: using background for no reason
switch(MY_frameCount){
case 1:
background('blue')
break
case 2:
background("darkgreen")
break
case 376:
background(crimson)
// break
}
MY_frameCount ++
or:
if(Math.random() < 0.1){
fill(Math.random() * 255, Math.random() * 255, Math.random() * 255)
} // this should on average fill with random color every 10 frames
I've made a square grid on top of the canvas and also a cruve (that is meant to have a fading trail). I made them seperately and tried combining them so the curve would appear on top of the grid. However, it doesn't show the curve.
I've commented out the grid so it's easier to see the curve.
How do I get this to work?
var cols = 10;
var rows = 10;
var t = 0;
var particleArray = [];
function setup() {
createCanvas(600, 600);
background(0);
fill(100);
rect(0, 0, 550, 550, 25);
}
// blue grid
function draw() {
/*for (var c = 0; c < cols; c++) {
for (var r = 0; r < rows; r++) {
var XO = 25 + c * 50;
var YO = 25 + r * 50;
stroke(0);
fill(100,149,237);
rect(XO, YO, 50, 50);
noLoop();
// :(
}
}
*/
//curve
y = width / 2 + 270 * sin(3 * t + PI / 2) - 25;
x = height / 2 + 270 * sin(1 * t) - 25;
particleArray.push(new Particle(x, y, t));
for (i=0; i<particleArray.length; i++) {
particleArray[i].show(t);
}
if (particleArray.length > 700) {
particleArray.shift();
}
t += .01;
}
function Particle(x, y, t) {
this.x = x;
this.y = y;
this.t = t;
this.show = function(currentT) {
var _ratio = t / currentT;
_alpha = map(_ratio, 0, 1, 0, 255); //points will fade out as time elaps
fill(255, 255, 255, _alpha);
ellipse(x, y, 5, 5);
}
}
I don't know if this was intentional but you called noLoop() function where you're drawing the grid. If you comment that out it works.