I am currently trying to create a grid of tiles in PROCESSING.... and I want each tile to appear after the other. (First row, left to right, second row, left to right and so on).... I get it to make each row of tiles appear one by one by a combination of frameCount and modulo in the nested loop.... but how to let each tile appear after another?
I've tried using the same method on the x-axis loop - this makes the grid appear from LEFT/UP to RIGHT/DOWN.... I tried changing the frameCount by multiplying times 10.... but this doesn't seem to be the correct maths.... do I need to use a conditional statement on one of the loops? Like if tiles is equal times round second row, third and so on? This is what I came up with so far:
void setup() {
size(500, 500);
}
void draw() {
background(255);
rectMode(CENTER);
float tiles = 10;
float tileSize = width/tiles;
translate(tileSize/2, tileSize/2);
for (int x = 0; x < tiles; x++) {
for (int y = 0; y < frameCount/tiles % tiles; y++) {
fill(0, 255, 0);
rect(x*tileSize, y*tileSize, tileSize, tileSize);
}
}
}
Thank you for any kind of help or hint!
My Processing is broken for some reason, you can past the following code to the p5js online editor
Is this what you want?
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
let tiles = 10;
let tileSize = width/tiles;
for(let y = 0; y < tiles; y++){
for(let x = 0; x < tiles; x++){
if(x + 10*y < frameCount)
rect(x*tileSize, y*tileSize, tileSize, tileSize)
}
}
}
https://editor.p5js.org/
Related
(please don't mark this question as not clear, I spent a lot of time posting it ;) )
Okay, I am trying to make a simple 2d java game engine as a learning project, and part of it is rendering a filled polygon as a feature.
I am creating this algorithm my self, and I really can't figure out what I am doing wrong.
My though process is something like so:
Loop through every line, get the number of points in that line, then get the X location of every point in that line,
Then loop through the line again this time checking if the x in the loop is inside one of the lines in the points array, if so, draw it.
Disclaimer: the Polygon class is another type of mesh, and its draw method returns an int array with lines drawn through each vertex.
Disclaimer 2: I've tried other people's solutions but none really helped me and none really explained it properly (which is not the point in a learning project).
The draw methods are called one per frame.
FilledPolygon:
#Override
public int[] draw() {
int[] pixels = new Polygon(verts).draw();
int[] filled = new int[width * height];
for (int y = 0; y < height; y++) {
int count = 0;
for (int x = 0; x < width; x++) {
if (pixels[x + y * width] == 0xffffffff) {
count++;
}
}
int[] points = new int[count];
int current = 0;
for (int x = 0; x < width; x++) {
if (pixels[x + y * width] == 0xffffffff) {
points[current] = x;
current++;
}
}
if (count >= 2) {
int num = count;
if (count % 2 != 0)
num--;
for (int i = 0; i < num; i += 2) {
for (int x = points[i]; x < points[i+1]; x++) {
filled[x + y * width] = 0xffffffff;
}
}
}
}
return filled;
}
The Polygon class simply uses Bresenham's line algorithm and has nothing to do with the problem.
The game class:
#Override
public void load() {
obj = new EngineObject();
obj.addComponent(new MeshRenderer(new FilledPolygon(new int[][] {
{0,0},
{60, 0},
{0, 60},
{80, 50}
})));
((MeshRenderer)(obj.getComponent(MeshRenderer.class))).color = CYAN;
obj.transform.position.Y = 100;
}
The expected result is to get this shape filled up.(it was created using the polygon mesh):
The actual result of using the FilledPolygon mesh:
You code seems to have several problems and I will not focus on that.
Your approach based on drawing the outline then filling the "inside" runs cannot work in the general case because the outlines join at the vertices and intersections, and the alternation outside-edge-inside-edge-outside is broken, in an unrecoverable way (you can't know which segment to fill by just looking at a row).
You'd better use a standard polygon filling algorithm. You will find many descriptions on the Web.
For a simple but somewhat inefficient solution, work as follows:
process all lines between the minimum and maximum ordinates; let Y be the current ordinate;
loop on the edges;
assign every vertex a positive or negative sign if y ≥ Y or y < Y (mind the asymmetry !);
whenever the endpoints of an edge have a different sign, compute the intersection between the edge and the line;
you will get an even number of intersections; sort them horizontally;
draw between every other point.
You can get a more efficient solution by keeping a trace of which edges cross the current line, in a so-called "active list". Check the algorithms known as "scanline fill".
Note that you imply that pixels[] has the same width*height size as filled[]. Based on the mangled output, I would say that they are just not the same.
Otherwise if you just want to fill a scanline (assuming everything is convex), that code is overcomplicated, simply look for the endpoints and loop between them:
public int[] draw() {
int[] pixels = new Polygon(verts).draw();
int[] filled = new int[width * height];
for (int y = 0; y < height; y++) {
int left = -1;
for (int x = 0; x < width; x++) {
if (pixels[x + y * width] == 0xffffffff) {
left = x;
break;
}
}
if (left >= 0) {
int right = left;
for (int x = width - 1; x > left; x--) {
if (pixels[x + y * width] == 0xffffffff) {
right = x;
break;
}
}
for (int x = left; x <= right; x++) {
filled[x + y * width] = 0xffffffff;
}
}
}
return filled;
}
However this kind of approach relies on having the entire polygon in the view, which may not always be the case in real life.
This is a follow-up post to my previous question, here. I got a remarkable response to instead of using array data tracking, to use matrixes. Now, the code here works just as planned (as in, the rectangles somewhat most of the time get filled in properly with white), but it's very inconsistent. When holding the left or right mouse button the colors phase over each other in a battle of randomness, and I don't know nearly that much about why this is happening. Just for reference, I'm using Java in Processing 3.
This is a result that I made with the project. As you can see, it looks fine.
Except for that jitter when hovering over a rect, and that more than not the rectangles are not being filled in half the time. And plus, the hover color is cycling almost randomly.
int cols, rows;
int scl = 20;
boolean[][] matrix = new boolean[scl+1][scl+1];
void setup() {
size(400, 400);
int w = 400;
int h = 400;
cols = w / scl;
rows = h / scl;
}
void draw() {
background(255);
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
int xpos = x*scl;
int ypos = y*scl;
stroke(55);
if ((mouseX >= xpos && mouseX <= xpos+scl) &&
(mouseY >= ypos && mouseY <= ypos+scl)) {
fill(75);
if (mousePressed == true) {
println("Clicked at: " + xpos + " and " + ypos);
if (!matrix[xpos/scl][ypos/scl]) {
matrix[xpos/scl][ypos/scl] = true;
} else {
matrix[xpos/scl][ypos/scl] = false;
}
fill(100);
//here is the desired location for the fill to remain constant even
//after unclicking and leaving hover
}
println("Mouse at: " + xpos + " and " + ypos);
} else {
fill(50);
}
if (matrix[x][y]) {
//fill(204, 102, 0);
fill(240);
rect(xpos, ypos, scl, scl);
}
rect(xpos, ypos, scl, scl);
}
}
}
Remeber that Processing fires the draw() function 60 times per second.
So your check for whether the mouse is pressed is happening 60 times per second. That means you're toggling the state of whatever cell the mouse is in 60 times per second.
To fix that problem, you might switch to using the event functions like mousePressed() instead of constantly polling every frame.
From the reference:
int value = 0;
void draw() {
fill(value);
rect(25, 25, 50, 50);
}
void mousePressed() {
if (value == 0) {
value = 255;
} else {
value = 0;
}
}
As for certain cells being skipped over, that's because when you move the mouse, it doesn't actually go through every pixel. It "jumps" from frame to frame. Those jumps are usually small enough that humans don't notice it, but they're large enough that it's skipping over cells.
One solution to this is to use the pmouseX and pmouseY variables to calculate a line from the previous mouse position to the current mouse position, and fill in any cells that would have been hit along the way.
I am trying to render pixels from an array.
I have an array of data that looks like this (except much larger). From this array I would like to somehow render it so that each number in the array corresponds to a pixel with a shade of gray based on the number value. (0.0 would be white, and 1.0 would be black)
I don't know where to start.
For the array you have given; If you know the width and height of the image you want rendered you can do this:
int indx = 0;
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
glColor3d(data[indx],data[indx],data[indx]);
//drawing of it goes here; assuming glVertex2d(x,y);
indx++;
}
}
For this to work it should be known that width*height < data.length. Increment index for each pixel drawn to go to the next number in the array and draw it accordingly.
Modify the x and y so it draws where you want. Say if locX = locY = 10 then depending on the viewport you should have already set up, then the image will start rendering 10px away from (probably) either the top left or bottom left corner. This part is simple maths if you have already started to learn how to draw in OpenGl and/or LWJGL.
int locX, locY;
int indx = 0;
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
glColor3d(data[indx],data[indx],data[indx]);
glVertex2d(locX + x, locY + y);
indx++;
}
}
Hope this helps.
So the title pretty much explains it all, recently I have learned about 2D arrays but I am a little confused on how to make the 2D array move correctly in this Space Invaders game I am creating.
Right now I have Aliens moving left to right (and vice versa), however, they don't all move down at the same time, they move down column by column. Anyone know where to edit the code?
Here is my code for the Aliens:
class Aliens {
int x = 100, y = 75, deltaX = 1;
Aliens (int x, int y) {
this.x = x;
this.y = y;
}
void drawAlien() {
fill(255);
rect(x, y, 25, 25);
}
void moveAlien() {
x = x + deltaX;
if (x >= width) {
y = y + 20;
deltaX = - deltaX;
} else if (x <=0) {
y = y + 20;
deltaX = - deltaX;
}
}
void updateAlien() {
drawAlien();
moveAlien();
}
}
and my main class:
import ddf.minim.*;
//Global Variables
PImage splash;
PFont roboto;
Defender player;
Aliens[][] alienArray = new Aliens[15][3];
Missile missile;
int gameMode = 0;
int score = 0;
void setup() {
size(1000, 750);
rectMode(CENTER);
textAlign(CENTER, CENTER);
splash = loadImage("Splash.png");
player = new Defender();
for (int row = 0; row < 15; row++) {
for (int column = 0; column < 3; column++) {
alienArray[row][column] = new Aliens((row + 1) * 50, (column + 1) * 50);
}
}
roboto = createFont("Roboto-Regular.ttf", 32);
textFont(roboto);
}
void draw() {
if (gameMode == 0) {
background(0);
textSize(75);
text("Space Invaders", width/2, height/8);
textSize(25);
text("Created by Ryan Simms", width/2, height/4);
textSize(45);
text("Press SPACE to Begin", width/2, height - 100);
image(splash, width/2-125, height/4 + 75);
} else if (gameMode == 1) {
background(0);
score();
player.updateDefender();
for (int row = 0; row < 10; row ++) {
for (int column = 0; column < 3; column++) {
alienArray[row][column].updateAlien();
}
}
if (missile != null) {
missile.updateMissile();
}
if (keyPressed) {
if (key == ' ') {
if (missile == null) {
missile = new Missile(player.x);
}
}
}
if (missile != null) {
if (missile.y <= 0) {
missile = null;
}
}
}
}
void score() {
textSize(20);
text("Score: " + score, 40, 15);
}
void keyPressed() {
if (key == ' ') {
gameMode = 1;
}
}
The logic flaw is in the moveAlien() method. You move the x position of an alien by a certain delta. If it is detected that the alien has passed some screen boundary (the x >= width and x <=0 checks), you invert the delta to reverse the movement of the alien, and also update the y position to have it move down.
Since the aliens are oriented in vertical columns, one column will always reach such a boundary while the others haven't yet. So that column will go down, and also begin reverting its movement. The other columns will then "catch up" later. So not only do they move down per column, the columns will also end up moving through one another.
You'll have to implement some logic to have your aliens move as a block, by detecting when the rightmost remaining alien has reached the right boundary, or the leftmost remaining alien has reached the left boundary, and then doing an update on all aliens to move down.
The idea of having each alien have its own state, putting the logic for controlling it in the alien class and calling that is actually good object-oriented design. It just so happens that for Space Invaders, the aliens all affect one another because they move in a block. As a result, your design results in them having too much individuality. Perhaps you can add some class that maintains state for the invader array as a whole (such as the leftmost and rightmost column still having an alien, direction of the entire block), control that in your movement loop and have it update the alien's location in turn.
I am experimenting with game development in java. As of now, I can use the screen class to render to the Canvas of an image through pixel array. However, whenever I attempt to render to the canvas through the pixel array within the other class, it reads the pixels array's content. x y numbers and all but, does not render it to the canvas at all even though the other class extends the screen class (thus inheriting the pixels array and the x, y numbers).
What is causing this? How do I go about fixing it?
from the other class:
void origin(){
if(x <= ax && y <= ay)
pixels[ox + oy * width] = 0xff00ff;
}
From the screen class:
void waves(){
orga = new Organism(width, height);
for(y = 0; y < height; y++){
for(x = 0; x < width; x++){
Color wacol = new Color(0, 0, u);
int water = wacol.getRGB();
pixels[x + y * width] = water;
orga.origin();
}
}
}
Extending the class isn't enough, it has to be hooked up to the screen in the same way as the pixel array that works.