Hi, how would I go about creating a grid of random(); dice that respond to a PImage(); in 2D (like the image below) or a 3D (heightmap)?
Now
-
start by loading the start image
-
Go through it pixel by pixel. The reference for pixels and image is your friend here. See below.
-
Then check the brightness for the pixel and use
text (1 or 2 or 3....)
in a grid corresponding to the image -
Later you can replace the numbers by images of the dice
See pixels[] / Reference / Processing.org
The dice
(not by me)
/*** Constants ***/
final int NUM_SIDES = 6; //Sides on the dice
final int NUM_DICE = 11; //The number of dices used
/*** Variables ***/
int[] rolls = new int[NUM_DICE]; //array to store dice roll
void setup() {
size(500, 500);
message_draw("Click to roll");
dice_roll();
}
void draw() {
for (int diceIndex = 0; diceIndex < NUM_DICE; diceIndex++) {
dice_draw( diceIndex, rolls[diceIndex] );
}
}
// ---------------------------------------------------------------------------------------------------
void mousePressed() {
dice_roll();
}
void message_draw(String message) {
//Display the given message in the centre of the window.
textSize(24);
fill(0);
text(message, (width-textWidth(message))/2, height/2);
}
void dice_roll() {
for (int i=0; i < NUM_DICE; i++) {
rolls[i]= 1 + int(random(NUM_SIDES));
}
}
void dice_draw(int position, int value) {
/* Draw one dice in the canvas.
* position - must be 0..NUM_DICE-1, indicating which dice is being drawn
* value - must be 1..6, the amount showing on that dice
*/
final float X_SPACING = (float)width/NUM_DICE; //X spacing of the dice
final float DIE_SIZE = X_SPACING*0.8; //width and height of one die
final float X_LEFT_DIE = X_SPACING*0.1; //left side of the leftmost die
final float Y_OFFSET = X_SPACING*0.15; //slight Y offset of the odd-numbered ones
final float Y_POSITION = height-DIE_SIZE-Y_OFFSET; //Y coordinate of most dice
final float PIP_OFFSET = DIE_SIZE/3.5; //Distance from centre to pips, and between pips
final float PIP_DIAM = DIE_SIZE/5; //Diameter of the pips (dots)
//From the constants above, and which dice it is, find its top left corner
float dieX = X_LEFT_DIE+position*X_SPACING;
float dieY = Y_POSITION-Y_OFFSET*(position%2);
//1.Draw a red square with a black outline
stroke(0); //Black outline
fill(255, 0, 0); //Red fill
rect(dieX, dieY, DIE_SIZE, DIE_SIZE);
//2.Draw the pips (dots)
fill(255); //White dots
stroke(255); //White outline
//The centre dot (if the value is odd, 1, 3, 5)
if (1 == value%2) {
ellipse(dieX+DIE_SIZE/2, dieY+DIE_SIZE/2, PIP_DIAM, PIP_DIAM);
}
//The top-left and bottom-right dots (if the value is more than 1)
if (value>1) {
ellipse(dieX+DIE_SIZE/2-PIP_OFFSET,
dieY+DIE_SIZE/2+PIP_OFFSET, PIP_DIAM, PIP_DIAM);
ellipse(dieX+DIE_SIZE/2+PIP_OFFSET,
dieY+DIE_SIZE/2-PIP_OFFSET, PIP_DIAM, PIP_DIAM);
}
//The bottom-left and top-right dots (if the value is more than 3)
if (value>3) {
ellipse(dieX+DIE_SIZE/2+PIP_OFFSET,
dieY+DIE_SIZE/2+PIP_OFFSET, PIP_DIAM, PIP_DIAM);
ellipse(dieX+DIE_SIZE/2-PIP_OFFSET,
dieY+DIE_SIZE/2-PIP_OFFSET, PIP_DIAM, PIP_DIAM);
}
//The left and right dots (only if the value is 6)
if (value==6) {
ellipse(dieX+DIE_SIZE/2-PIP_OFFSET,
dieY+DIE_SIZE/2, PIP_DIAM, PIP_DIAM);
ellipse(dieX+DIE_SIZE/2+PIP_OFFSET,
dieY+DIE_SIZE/2, PIP_DIAM, PIP_DIAM);
}
}
//
Hello @asymmetric,
You have already done a lot of work from your other posts that you can reuse.
I always think this trough and mentally (or written as below) go through steps required and then consider what code (always lots of options) to use.
Steps I took in my first attempt at this:
-
Resize image. This makes it easy to extract a pixel and simplifies things… no need to get an average color of a section. Explore a more advanced approach later…
-
Create a grid that is the size (cells x cells) of the resized image; size of each cell will be larger.
-
Color each cell of the grid with the brightness (other options here) of the pixel.
-
Brightness is 0 to 255 and you can map this to 0 to 6; do the math or use the helper function.
The result will be a float and only use the integer component of this. -
You can then use 0 to 5 to get the dice image for brightness.
It may not be an image and generated; I generated the face of each dice… this was just another grid (filtered the faces) for me.
You have some options on how to do this part.
I leave that with you… give it some thought.
At first I just colored the grid with 6 shades of gray:
I then replaced the 6 shades of gray with the face of a die:
:)
Thank you @glv! I now understand how to rasterize an image, but how do I control the placement of the dice circles within each pixel?
You mean a single dice? I’ve shown code above
Plus map() the brightness of each pixel to 1…6 and draw the dice number
int showDiceNumber = map( myBrightness,
0,255,
6, 1 ); // wild guess
I have the following code so far… the pixelated rasterized image (via Tim Rodenbroeker).
PImage img;
void setup(){
size(700,700);
img = loadImage("IMG_7741.jpeg");
}
void draw(){
background(#f1f1f1);
//noSrtoke();
float tilesX = 120;
float tilesY = tilesX;
float tileW = width / tilesX;
float tileH = height/ tilesY;
translate(-30,-20);
for (int x = 0; x < tilesX; x++){
for (int y = 0; y < tilesY; y++){
int px = int(x*tileW);
int py = int(y*tileH);
color c = img.get(px,py);
fill(c);
rect(x*tileW, y*tileH, tilesX, tilesY);
}
}
}
That’s what I meant too
See above
@Chrisir I’m not sure how to weave your dice code in with my pixelated grid code?
After I add brightness, get pixel color, and map the pixels using the sides of the dice… what do I do next?
color c = img.get(pX, pY);
float b = brightness(c);
float s = map(b, 0, 255, 1, 6); // 1-6 dice sides
I also have the following dice program but I’m not sure how to weave the dice in as the image rasterization.
void setup()
{
size(500,600);
textAlign(CENTER);
noLoop();
}
void draw()
{
clear();
int total = 0;
for (int y = 0; y < 500; y = y + 50) {
for ( int x = 0; x < 500; x = x + 50) {
Die die = new Die( x, y);
die.show();
print( die.dots );
total = total + die.dots;
}
}
textSize(24);
text("Sum : " + total, 250, 550);
}
void mousePressed()
{
redraw();
}
class Die
{
//variable declarations here
int dots;
int myX;
int myY;
Die(int x, int y) //constructor
{
roll();
myX = x;
myY= y;
}
void roll()
{
if (random(6) <= 1)
{
dots = 1;
} else if (random(6) <= 2)
{
dots = 2;
} else if (random(6) <= 3)
{
dots = 3;
} else if (random(6) <= 4)
{
dots = 4;
} else if (random(6) <= 5)
{
dots = 5;
} else if (random(6) <= 6)
{
dots = 6;
}
}
void show()
{
fill(255,255,255);
rect(myX, myY, 50, 50);
fill(0, 0, 0);
if (dots == 1)
{
ellipse(myX+25, myY+25, 10, 10);
} else if (dots == 2)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
} else if (dots == 3)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+25, myY+25, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
} else if (dots == 4)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+10, myY+10, 10, 10);
ellipse(myX+40, myY+40, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
} else if (dots == 5)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+10, myY+10, 10, 10);
ellipse(myX+40, myY+40, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
ellipse(myX+25, myY+25, 10, 10);
} else if (dots == 6)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+10, myY+25, 10, 10);
ellipse(myX+10, myY+10, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
ellipse(myX+40, myY+25, 10, 10);
ellipse(myX+40, myY+40, 10, 10);
}
}
}
That’s really simple
Instead of using random just pass the s you calculated with
map() to the class dice
like die.show(s);
So that’s the dots in the class
Try to integrate this inside of your nested for loop.
Before the dice part inside the for loop
increase pX and pY by 1
Make sure the for loop matches the number of pixel in your image
You are almost there
OR in the other code replace this
fill(c);
rect(x*tileW, y*tileH, tilesX, tilesY);
with the s= map… and dice stuff
Like this?
PImage img;
void setup(){
size(700,700);
img = loadImage("IMG_7741.jpeg");
}
void draw(){
background(#f1f1f1);
//noSrtoke();
float tilesX = 80;
float tilesY = tilesX;
float tileW = width / tilesX;
float tileH = height/ tilesY;
translate(-30,-20);
for (int x = 0; x < tilesX; x++){
for (int y = 0; y < tilesY; y++){
int px = int(x*tileW);
int py = int(y*tileH);
color c = img.get(px,py);
fill(c);
float b = brightness(c);
float s = map(b, 0, 255, 1, 6); // 1-6 dice sides
rect(x*tileW, y*tileH, tilesX, tilesY);
Die die = new Die( x, y);
die.show(s);
print( die.dots );
total = total + die.dots;
}
}
}
class Die
{
//variable declarations here
int dots;
int myX;
int myY;
Die(int x, int y) //constructor
{
roll();
myX = x;
myY= y;
}
void roll()
{
if (s(6) <= 1)
{
dots = 1;
} else if (random(6) <= 2)
{
dots = 2;
} else if (random(6) <= 3)
{
dots = 3;
} else if (random(6) <= 4)
{
dots = 4;
} else if (random(6) <= 5)
{
dots = 5;
} else if (random(6) <= 6)
{
dots = 6;
}
}
void show()
{
fill(255,255,255);
rect(myX, myY, 50, 50);
fill(0, 0, 0);
if (dots == 1)
{
ellipse(myX+25, myY+25, 10, 10);
} else if (dots == 2)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
} else if (dots == 3)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+25, myY+25, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
} else if (dots == 4)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+10, myY+10, 10, 10);
ellipse(myX+40, myY+40, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
} else if (dots == 5)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+10, myY+10, 10, 10);
ellipse(myX+40, myY+40, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
ellipse(myX+25, myY+25, 10, 10);
} else if (dots == 6)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+10, myY+25, 10, 10);
ellipse(myX+10, myY+10, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
ellipse(myX+40, myY+25, 10, 10);
ellipse(myX+40, myY+40, 10, 10);
}
}
}
Get rid of this
AND
For Dice use x*tileW, y*tileH
I think x and y will be enough here
Like this? I’m still receiving compiler errors from processing. Thank you for your help!
PImage img;
void setup(){
size(700,700);
img = loadImage("IMG_7741.jpeg");
}
void draw(){
background(#f1f1f1);
//noSrtoke();
float tilesX = 80;
float tilesY = tilesX;
float tileW = width / tilesX;
float tileH = height/ tilesY;
translate(-30,-20);
for (int x = 0; x < tilesX; x++){
for (int y = 0; y < tilesY; y++){
Die die = new Die(x*tileW, y*tileH );
die.show(s);
//total = total + die.dots;
int px = int(x);
int py = int(y);
color c = img.get(px,py);
fill(c);
float b = brightness(c);
float s = map(b, 0, 255, 1, 6); // 1-6 dice sides
//rect(x*tileW, y*tileH, tilesX, tilesY);
}
}
}
class Die
{
//variable declarations here
int dots;
int myX;
int myY;
Die(float x, float y) //constructor
{
roll();
myX = x;
myY= y;
}
void roll()
{
if (s(6) <= 1)
{
dots = 1;
} else if (random(6) <= 2)
{
dots = 2;
} else if (random(6) <= 3)
{
dots = 3;
} else if (random(6) <= 4)
{
dots = 4;
} else if (random(6) <= 5)
{
dots = 5;
} else if (random(6) <= 6)
{
dots = 6;
}
}
void show()
{
fill(255,255,255);
rect(myX, myY, 50, 50);
fill(0, 0, 0);
if (dots == 1)
{
ellipse(myX+25, myY+25, 10, 10);
} else if (dots == 2)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
} else if (dots == 3)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+25, myY+25, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
} else if (dots == 4)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+10, myY+10, 10, 10);
ellipse(myX+40, myY+40, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
} else if (dots == 5)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+10, myY+10, 10, 10);
ellipse(myX+40, myY+40, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
ellipse(myX+25, myY+25, 10, 10);
} else if (dots == 6)
{
ellipse(myX+10, myY+40, 10, 10);
ellipse(myX+10, myY+25, 10, 10);
ellipse(myX+10, myY+10, 10, 10);
ellipse(myX+40, myY+10, 10, 10);
ellipse(myX+40, myY+25, 10, 10);
ellipse(myX+40, myY+40, 10, 10);
}
}
}
This belongs after the line where you define s
Also since you read the source image
in the for loops, they must not exceed width and height of the image (is your image 80x80??)
When you draw on the screen you can use the multiply by tileW …
Please debug your code
Please tell us the errors you get
You are almost there
You forgot to implement your s here -
int s in brackets () and
dots=s;
Delete this please
Thank you