I am getting this 'requestAnimationFrame' error with this code. I guess there's something with the for loop that causes the problem but I can't figure an alternative way of getting the same visual result. Any idea?
let zoff = 0;
function setup() {
createCanvas(windowWidth, windowHeight);
background(0);
}
function draw() {
background(0);
translate(width / 2, height / 2);
scale(40);
noStroke();
fill(255);
for (let a = 0; a < 7; a += 0.0012) {
let x = cos(zoff) * 20 * sin(a);
let y = cos(zoff+x/2) * 10 * cos(a);
let e = cos(x) / sin(y) + zoff;
circle(sin(e) * y, cos(e) * y, 0.091);
}
zoff += map(mouseX, 0, width, -0.03, +0.03);
}
This isn't an error, just a warning. It just means your frame is taking a relatively long time to draw. Since each frame you are looping 7 / 0.0012 = 5833 loops * 8 trig functions = 46664 trig calls per frame. If you are doing something like drawing frames to be exported and rendered as a video, that would be safe to ignore, but if this is for something real time, you'll have to figure out some optimizations.
Well it doesn't give me the same, I just copied it into https://editor.p5js.org/ and works perfectly, maybe it's something with your html file. It also seems to have nice performance, so if copying it into a new sketch doesn't work try commenting different parts of the code or maybe using a different browser. It might just be a p5.js bug.
Related
I have been working on a doom/wolfenstein style raycaster for a while now. I implemented the "floor raycasting" to the best of my ability, roughly following a well known raycaster tutorial. It almost works, but the floor tiles seem slightly bigger than they should be, and they don't "stick", as in they don't seem to align properly and they slide slightly as the player moves/rotates. Additionally, the effect seems worsened as the FOV is increased. I cannot figure out where my floor casting is going wrong, so any help is appreciated.
Here is a (crappy) gif of the glitch happening
Here is the most relevant part of my code:
void render(PVector pos, float dir) {
ArrayList<FloatList> dists = new ArrayList<FloatList>();
for (int i = 0; i < numColumns; i++) {
float curDir = atan((i - (numColumns/2.0)) / projectionDistance) + dir;
// FloatList because it returns a few pieces of data
FloatList curHit = cast(pos, curDir);
// normalize distances with cos
curHit.set(0, curHit.get(0) * cos(curDir - dir));
dists.add(curHit);
}
screen.beginDraw();
screen.background(50);
screen.fill(0, 30, 100);
screen.noStroke();
screen.rect(0, 0, screen.width, screen.height/2);
screen.loadPixels();
PImage floor = textures.get(4);
// DRAW FLOOR
for (int y = screen.height/2 + 1; y < screen.height; y++) {
float rowDistance = 0.5 * projectionDistance / ((float)y - (float)rY/2);
// leftmost and rightmost (on screen) floor positions
PVector left = PVector.fromAngle(dir - fov/2).mult(rowDistance).add(p.pos);
PVector right = PVector.fromAngle(dir + fov/2).mult(rowDistance).add(p.pos);
// current position on the floor
PVector curPos = left.copy();
PVector stepVec = right.sub(left).div(screen.width);
float b = constrain(map(rowDistance, 0, maxDist, 1, 0), 0, 1);
for (int x = 0; x < screen.width; x++) {
color sample = floor.get(floor((curPos.x - floor(curPos.x)) * floor.width), floor((curPos.y - floor(curPos.y)) * floor.height));
screen.pixels[x + y*screen.width] = color(red(sample) * b, green(sample) * b, blue(sample) * b);
curPos.add(stepVec);
}
}
updatePixels();
}
If anyone wants to look at the full code or has any questions, ask away.
Ok, I seem to have found a "solution". I will be the first to admit that I do not understand why it works, but it does work. As per my comment above, I noticed that my rowDistance variable was off, which caused all of the problems. In desperation, I changed the FOV and then hardcoded the rowDistance until things looked right. I plotted the ratio between the projectionDistance and the numerator of the rowDistance. I noticed that it neatly conformed to a scaled cos function. So after some simplification, here is the formula I came up with:
float rowDistance = (rX / (4*sin(fov/2))) / ((float)y - (float)rY/2);
where rX is the width of the screen in pixels.
If anyone has an intuitive explanation as to why this formula makes sense, PLEASE enlighten me. I hope this helps anyone else who may have this problem.
I have to create these two included images using the turtle function and the loop method on p5js and I am struggling I was given https://editor.p5js.org/dpapanik/sketches/_lbGWWH6N this code on p5js as a start please help, thanksenter image description here
So I've played around with some of the stuff for awhile, and I've created two functions. One that makes a single quadrant of the first problem, and one that creates a single wiggly line for the second problem. This is just a base for you to work of in this process. Here's each of the functions. Also, note that each of them takes in the turtle as a parameter:
function makeLineQuadrant(turtle) {
// this currently makes the top left corner:
let yVal = windowWidth * 0.5;
let xVal = windowWidth * 0.5;
for (let i = 0; i < 13; i++) {
// loop through the 12 lines in one quadrant
turtle.face(0); // reset for the new round
turtle.penUp();
let startLeft = i * ((windowWidth * 0.5) / 12); // decide which component on the button we should start at
let endTop = (12 - i) * ((windowWidth * 0.5) / 12); // how far down the y-axis should we go? You should write this out on paper to see how it works
turtle.goto(startLeft, yVal);
turtle.penDown();
let deg = turtle.angleTo(xVal, endTop); // what direction do I need to turn?
turtle.face(deg);
let distance = turtle.distanceTo(xVal, endTop); // how far away is it?
turtle.forward(distance);
}
}
I tried to add a few comments throughout, but if there is any step that is confusing, please add a comment.
function makeSquiggle(turtle) {
turtle.setColor(color(random(0, 255), random(0, 255), random(0, 255)));
let middleX = windowWidth * 0.5, middleY = windowHeight * 0.5;
turtle.goto(windowWidth * 0.5, windowHeight * 0.5);
// let's start moving in a random direction UNTIL our distance from the center is greater than some number X
let X = 300; // arbitrary distance from center
// some variables that can help us get some random movement for our turtle:
let turtleXvel = random(-3, 3), turtleYvel = random(-3, 3);
while (turtle.distanceTo(middleX, middleY) < X) {
turtle.face(0);
// calculate movement:
let newXmove = turtle.x + turtleXvel, newYmove = turtle.y + turtleYvel;
// direct our turtle:
turtle.face(turtle.angleTo(newXmove, newYmove));
let distance = turtle.distanceTo(newXmove, newYmove); // how far away is it?
// move our turtle
turtle.penDown();
turtle.forward(distance);
// change the velocity a little bit for a smooth curving:
turtleXvel += random(-1, 1);
turtleYvel += random(-1, 1);
}
}
Note that I'm changing the velocities instead of the position directly. This is a classic Calculus / Physics problem where the derivative gives us a smaller range, so adjusting turtleXvel and turtleYvel change the position in much less drastic ways versus:
turtle.x += random(-1, 1);
turtle.y += random(-1, 1);
You should look at the difference as well to visualize this. Beyond this is working with these structural components to finish this up!
The code is supposed to fade and copy the window's image to a buffer f, then draw f back onto the window but translated, rotated, and scaled. I am trying to create an effect like a feedback loop when you point a camera plugged into a TV at the TV.
I have tried everything I can think of, logged every variable I could think of, and still it just seems like image(f,0,0) is doing something wrong or unexpected.
What am I missing?
Pic of double image mirror about x-axis:
PGraphics f;
int rect_size;
int midX;
int midY;
void setup(){
size(1000, 1000, P2D);
f = createGraphics(width, height, P2D);
midX = width/2;
midY = height/2;
rect_size = 300;
imageMode(CENTER);
rectMode(CENTER);
smooth();
background(0,0,0);
fill(0,0);
stroke(255,255);
}
void draw(){
fade_and_copy_pixels(f); //fades window pixels and then copies pixels to f
background(0,0,0);//without this the corners dont get repainted.
//transform display window (instead of f)
pushMatrix();
float scaling = 0.90; // x>1 makes image bigger
float rot = 5; //angle in degrees
translate(midX,midY); //makes it so rotations are always around the center
rotate(radians(rot));
scale(scaling);
imageMode(CENTER);
image(f,0,0); //weird double image must have something not working around here
popMatrix();//returns window matrix to normal
int x = mouseX;
int y = mouseY;
rectMode(CENTER);
rect(x,y,rect_size,rect_size);
}
//fades window pixels and then copies pixels to f
void fade_and_copy_pixels(PGraphics f){
loadPixels(); //load windows pixels. dont need because I am only reading pixels?
f.loadPixels(); //loads feedback loops pixels
// Loop through every pixel in window
//it is faster to grab data from pixels[] array, so dont use get and set, use this
for (int i = 0; i < pixels.length; i++) {
//////////////FADE PIXELS in window and COPY to f:///////////////
color p = pixels[i];
//get color values, mask then shift
int r = (p & 0x00FF0000) >> 16;
int g = (p & 0x0000FF00) >> 8;
int b = p & 0x000000FF; //no need for shifting
// reduce value for each color proportional
// between fade_amount between 0-1 for 0 being totallty transparent, and 1 totally none
// min is 0.0039 (when using floor function and 255 as molorModes for colors)
float fade_percent= 0.005; //0.05 = 5%
int r_new = floor(float(r) - (float(r) * fade_percent));
int g_new = floor(float(g) - (float(g) * fade_percent));
int b_new = floor(float(b) - (float(b) * fade_percent));
//maybe later rewrite in a way to save what the difference is and round it differently, like maybe faster at first and slow later,
//round doesn't work because it never first subtracts one to get the ball rolling
//floor has a minimum of always subtracting 1 from each value each time. cant just subtract 1 ever n loops
//keep a list of all the pixel as floats? too much memory?
//ill stick with floor for now
// the lowest percent that will make a difference with floor is 0.0039?... because thats slightly more than 1/255
//shift back and or together
p = 0xFF000000 | (r_new << 16) | (g_new << 8) | b_new; // or-ing all the new hex together back into AARRGGBB
f.pixels[i] = p;
////////pixels now copied
}
f.updatePixels();
}
This is a weird one. But let's start with a simpler MCVE that isolates the problem:
PGraphics f;
void setup() {
size(500, 500, P2D);
f = createGraphics(width, height, P2D);
}
void draw() {
background(0);
rect(mouseX, mouseY, 100, 100);
copyPixels(f);
image(f, 0, 0);
}
void copyPixels(PGraphics f) {
loadPixels();
f.loadPixels();
for (int i = 0; i < pixels.length; i++) {
color p = pixels[i];
f.pixels[i] = p;
}
f.updatePixels();
}
This code exhibits the same problem as your code, without any of the extra logic. I would expect this code to show a rectangle wherever the mouse is, but instead it shows a rectangle at a position reflected over the X axis. If the mouse is on the top of the window, the rectangle is at the bottom of the window, and vice-versa.
I think this is caused by the P2D renderer being OpenGL, which has an inversed Y axis (0 is at the bottom instead of the top). So it seems like when you copy the pixels over, it's going from screen space to OpenGL space... or something. That definitely seems buggy though.
For now, there are two things that seem to fix the problem. First, you could just use the default renderer instead of P2D. That seems to fix the problem.
Or you could get rid of the for loop inside the copyPixels() function and just do f.pixels = pixels; for now. That also seems to fix the problem, but again it feels pretty buggy.
If somebody else (paging George) doesn't come along with a better explanation by tomorrow, I'd file a bug on Processing's GitHub. (I can do that for you if you want.)
Edit: I've filed an issue here, so hopefully we'll hear back from a developer in the next few days.
Edit Two: Looks like a fix has been implemented and should be available in the next release of Processing. If you need it now, you can always build Processing from source.
An easier one, and works like a charm:
add f.beginDraw(); before and f.endDraw(); after using f:
loadPixels(); //load windows pixels. dont need because I am only reading pixels?
f.loadPixels(); //loads feedback loops pixels
// Loop through every pixel in window
//it is faster to grab data from pixels[] array, so dont use get and set, use this
f.beginDraw();
and
f.updatePixels();
f.endDraw();
Processing must know when it's drawing in a buffer and when not.
In this image you can see that works
I made a small "game" to test some stuttering I had noticed in my actual game, and I can't for the life of me figure out why this is happening. I made the simplest possible project I could to test this out, but I still get pretty heavy stuttering. The FPS is still 60, but every few seconds, sometimes more, the game will stutter.
I have tried it on both mobile and a high-end pc, and oddly enough, it's more noticeable on the PC, though it still occurs on mobile.
I can't upload a video of it, since it's gone in the recording, so feel free to compile the project yourself if you want to test it. Here's the code:
public class LagTest extends ApplicationAdapter {
SpriteBatch batch;
Texture dot;
float x;
float y;
float speed;
float dotWidth;
int screenWidth;
#Override
public void create () {
batch = new SpriteBatch();
dot = new Texture("dot.png");
x = 100;
y = Gdx.graphics.getHeight()/2 - dot.getHeight()/2;
speed = 500;
dotWidth = dot.getWidth();
screenWidth = Gdx.graphics.getWidth();
}
#Override
public void render () {
Gdx.gl.glClearColor(0.2f, 0.4f, 0.8f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(dot, x, y);
batch.end();
if (x < 0) {
speed = 500;
}
if (x > screenWidth - dotWidth) {
speed = -500;
}
x += speed * Gdx.graphics.getDeltaTime();
}
}
If anyone have some clue to what could be causing this, I'm all ears.
Edit:
So here's something fun. This only seems to occur in windowed mode, not in fullscreen. This might also be why it works better on mobile. Perhaps this is a bug then?
After trying some different methods (averaging delta / averaging raw delta / using raw delta / lowering frame rate to 30 / using a set delta each frame) getting the same stuttering on each one and then googling some on stuttering in windowed mode:
I would like to propose that the stuttering is not caused by LibGDX in itself, but rather is a general problem that occurs in windowed mode and which can have a number of different hardware-near causes. See here for one example and explanation: https://gamedev.stackexchange.com/questions/47356/why-would-a-borderless-full-screen-window-stutter-occasionally
I have written this code which, on a mouse button press, increases or decreases the number of circles visible, equally spaced around a circle.
int nbr_circles = 2;
void setup() {
size(600, 600);
smooth();
background(255);
}
void draw() {
background(255);
float cx = width/2.0;
float cy = height/2.0;
fill(0);
//float x, y; //
for (int i = 0; i < nbr_circles; i++)
{
float angle = i * TWO_PI / nbr_circles;
float x = cx + 110.0 * cos(angle);
float y = cy + 110.0 * sin(angle);
ellipse(x, y, 20, 20);
}
}
void mousePressed() {
if (mouseButton == LEFT) {
if (nbr_circles < 20)
nbr_circles = nbr_circles + 1;
} else if (mouseButton == RIGHT) {
if (nbr_circles > 2)
nbr_circles = nbr_circles - 1;
}
}
I would like to alter the code so that, with nbr_circles fixed at 10, only one circle is visible at a time, each in turn in successive frames.
I have changed the code a little. The mouse buttons do nothing and the nbr_circles is fixed at 10.
How can I now show one circle at a time?
show circle #1 -> hide circle #1, show circle #2 -> hide circle #2, show circle #3 … -> hide circle #9, show circle #10 -> hide circle #1, show circle #1…
Adjusted code - where is it going wrong?
int nbr_circles = 2;
int i = 1;
void setup () {
size (600, 600);
}
void draw () {
background (255);
fill (0);
float cx = width/2.0;
float cy = height/2.0;
float angle = i * TWO_PI / nbr_circles;
float x = cx + 110.0 * cos(angle);
float y = cy + 110.0 * sin(angle);
ellipse(x, y, 20, 20);
}
if (mouseButton == LEFT) {
if (ellipse(x,y,20,20))
rotate (angle);
}
Thanks in advance.
Taking a step back, I really suggest you start a bit smaller, instead of posting a new question every time you get stuck. It looks like you've got a fundamental misunderstanding of the basic syntax of Processing, so maybe you should go back and do some tutorials until you're more comfortable in it. That's probably the most "correct" answer I can give you, even though it's probably not what you're looking for.
To answer the question of why your adjusted code doesn't work, it's because none of the syntax makes sense. First of all, you've got an if statement outside of a function, which isn't valid. When do you expect that if statement to be executed?
Secondly, you've got the ellipse() function inside an if statement, but the ellipse() function doesn't return a boolean. What do you expect that to do? And finally, what do you expect that rotate function to do?
It seems like you're trying to copy-paste code you found on the internet without really understanding any of it. That's not going to work. You have to take a step back and understand the basics before you can expect to make a program that actually does what you want it to do.
If you edit your "adjusted code" to fix the problems I pointed out, I'll try to help you through the process, but you really should consider going back and starting smaller before trying to get somebody else's code you found on the internet to work.