Skip to content

Instantly share code, notes, and snippets.

@paulera
Last active March 8, 2017 03:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paulera/f53f664d51c0dd0df872fb5e89330329 to your computer and use it in GitHub Desktop.
Save paulera/f53f664d51c0dd0df872fb5e89330329 to your computer and use it in GitHub Desktop.
Card idea for teaching processing to kids. The contents of the function "draw2" can be written in the back of the card as they are, no modification needed.
drawGrid = true;
void drawOnce() {
fill(0);
PFont myFont = createFont("Impact", 35);
textFont(myFont);
textAlign(CENTER);
text("TRUCK DELIVERED BOMB", 10, 30, 380, 50);
noFill();
rect (40, 240, 250, 120);
rect (300, 280, 70, 80);
ellipse(90, 360, 50, 50);
ellipse(230, 360, 50, 50);
ellipse(340, 360, 50, 50);
fill(0);
PFont myFont = createFont("Arial", 20);
textFont(myFont);
textAlign(CENTER);
text("If you have no DISARM, look to one player and pretend you are driving a truck. If they don't get down, that person explodes with you.", 10, 500, 380, 100);
}
/*
GAME BASED ON https://www.explodingkittens.com/explodingkittensrules.pdf
KIDS WOULD CHOSE THE TYPE OF CARD AND CODE THE INNER PART. HERE IT IS THE
drawOnce FUNCTION NOW. TEXT CAN BE ADDED TO CHANGE THE CARD EFFECT A BIT
AND MAKE THE GAME MORE FUN / LET KIDS HAVE CONTROL OVER THE GAME RULES.
Players can't play with their cards, all goes to the pile and people pick
it up at random.
Card types:
Bomb = 4 cards - when you pick one from the pile, if you don't have a disarm, you explode, get out of the game and put the bomb back into the pile.
Disarm = 6 cards - avoid you to die when you pick a bomb from the pile.
Attack = 4 cards - Effect on another player - make them take cards from the pile, force to discard, etc
Skip = 4 cards - You don't need to pick a card when you play a skip
Favor = 4 cards - Can steal cards from another player
Shuffle = 4 cards - Shuffle the deck
See the future = 5 cards - Can see the top 3 cards on the deck. Must put back in the original order
Nope = 5 cards - cancel another player action. Can be played at any moment (except for bombs)
Other cards = Can have common actions like (play 2 of "whatever" and look for a defuser in the pile, then shuffle it)
*/
void setup() {
// Create the canvas. Standard proportion for Poker cards.
size (600, 840);
// Creates a card with a inner canvas of 700x500. The card itself will be
// slightly bigger than this. It is recommended that the screen be 100 pixels
// bigger than the card inner canvas
// creates a card with a inner canvas of 700x500
Bomb bombCard = new Bomb(); // official poker card proportions
// Draws the card with a grid (true)
bombCard.drawFront(true);
bombCard.drawSuits();
// Reset fills, stroke, colors, so they don't affect the drawing.
// Also set the inner canvas (0,0) point as the new starting point
// of coordinate system. Revert after drawing the card
try {
bombCard.prepareForDrawing();
drawOnce();
bombCard.revertFromDrawing();
} catch (Exception ex) {}
}
class Bomb extends BoBombGame {
public Bomb() {
this.colorInnerCanvasBorder = new int[]{ 180, 0, 0 };
this.colorBigBorder = new int[]{180, 0, 0};
this.colorCard = new int[]{0,0,0};
this.colorInnerCanvas = new int[]{255, 255, 255};
this.colorGridNumbers2 = new int[]{250, 0, 0};
}
public void drawSuitIcon() {
noFill();
textAlign(LEFT);
strokeWeight(6);
stroke(200);
bezier(129, 77, 62, 83, 147, 15, 80, 41);
strokeWeight(2);
stroke(180,0,0);
fill(250,250,0);
drawingUtils.star(132,75,5,15,6);
stroke(100);
fill(40);
ellipse(54,70,60,60);
rotate(PI/4);
translate(72,-28);
rect(0,0,30,15);
translate(-83,30);
rotate(-PI/4);
fill(255);
textFont(this.fontTitle);
text ("BOMB", 170,60);
textFont(this.fontSubtitle);
text ("Can only be avoided by a DISARM card", 170,80);
noFill();
}
}
abstract class BoBombGame extends Card {
public abstract void drawSuitIcon();
public void drawSuits() {
drawSuitIcon();
translate(width,height);
rotate(PI);
drawSuitIcon();
rotate(-PI);
translate(-width,-height);
}
}
class Card {
public int padding = 10;
public int radius = 20;
public int gridStep = 10;
public int textSizeGrid = 9;
public int[] colorBigBorder = {0, 0, 0};
public int[] colorCard = {255, 255, 255};
public int[] colorInnerCanvas = {25, 255, 255};
public int[] colorInnerCanvasBorder = { 0, 102, 153 };
public int[] colorGridNumbers = { 175, 175, 175 };
public int[] colorGridNumbers2 = { 0, 0, 0 };
public int[] colorGridNumbersHighlight = { 208, 19, 37 };
public int[] sizeInnerCanvas = {400, 600};
public PFont fontTitle = createFont("Impact", 35);
public PFont fontSubtitle = createFont("Arial", 20);
protected DrawingUtils drawingUtils = new DrawingUtils();
public Card() {
}
public Card(int innerCanvasWidth, int innerCanvasHeight) {
this.sizeInnerCanvas = new int[2];
this.sizeInnerCanvas[0] = innerCanvasWidth;
this.sizeInnerCanvas[1] = innerCanvasHeight;
}
public void prepareForDrawing() {
// translate the coordinates system to the inner canvas base point
// so the draw function can work inside it constraints properly
translate(this.calculateCanvasStartX(), this.calculateCanvasStartY());
// reset color, fill and etc
stroke(0); // black lines
fill (255, 255, 255, 0); // transparent
strokeWeight(3); // medium line weight
}
public void revertFromDrawing() {
translate(-this.calculateCanvasStartX(), -this.calculateCanvasStartY());
}
public void drawBase() {
background(255);
// Draws the outer border
this.fill2(colorBigBorder);
noStroke();
rect(0, 0, width, height, radius);
// Draws the card inner space
this.fill2(colorCard);
rect(padding, padding, width - (padding*2), height - (padding*2), radius);
}
public void drawFront(Boolean grid) {
if (grid) {
this.drawFrontWithGrid();
} else {
drawFrontNoGrid();
}
}
public void drawFrontWithGrid() {
this.drawBase();
this.paintInnerCanvas();
this.drawGrid();
this.drawInnerCanvasBorder();
this.drawGridText();
}
public void drawFrontNoGrid() {
this.drawBase();
this.paintInnerCanvas();
this.drawInnerCanvasBorder();
}
public int calculateCanvasStartX() {
return (int)(width - sizeInnerCanvas[0])/2;
}
public int calculateCanvasStartY() {
return (int)(height - sizeInnerCanvas[1])/2;
}
public void paintInnerCanvas() {
int canvasStartX = this.calculateCanvasStartX();;
int canvasStartY = this.calculateCanvasStartY();;
// Draws the inner canvas
noStroke();
this.fill2(colorInnerCanvas);
rect (
canvasStartX,
canvasStartY,
sizeInnerCanvas[0],
sizeInnerCanvas[1]
);
}
public void drawInnerCanvasBorder() {
int canvasStartX = this.calculateCanvasStartX();;
int canvasStartY = this.calculateCanvasStartY();;
// Draws the inner canvas
strokeWeight(4);
strokeJoin(ROUND);
this.stroke2(this.colorInnerCanvasBorder);
noFill();
rect (
canvasStartX,
canvasStartY,
sizeInnerCanvas[0],
sizeInnerCanvas[1]
);
}
public void drawGrid() {
int canvasStartX = this.calculateCanvasStartX();;
int canvasEndX = canvasStartX + sizeInnerCanvas[0];
int canvasStartY = this.calculateCanvasStartY();;
int canvasEndY = canvasStartY + sizeInnerCanvas[1];
int stepsX = sizeInnerCanvas[0]/this.gridStep + 1;
int stepsY = sizeInnerCanvas[1]/this.gridStep + 1;
// First, compute the X and Y positions for the grid,
// for better performance
int[] xStops = new int[stepsX];
int[] yStops = new int[stepsY];
for (int i = 0; i < stepsX; i++) {
xStops[i] = canvasStartX + (i * this.gridStep);
}
for (int i = 0; i < stepsY; i++) {
yStops[i] = canvasStartY + (i * this.gridStep);
}
// -----------------
// Soft lines
// -----------------
stroke(220);
strokeWeight(1);
for (int i = 0; i < stepsX; i++) {
line(xStops[i], canvasStartY - 10, xStops[i], canvasEndY);
}
for (int i = 0; i < stepsY; i++) {
line(canvasStartX - 10, yStops[i], canvasEndX, yStops[i]);
}
// -----------------
// Hard lines
// -----------------
stroke(200);
strokeWeight(2);
for (int i = 0; i < stepsX; i = i + 10) {
line(xStops[i], canvasStartY - 10, xStops[i], canvasEndY);
}
for (int i = 0; i < stepsY; i = i + 10) {
line(canvasStartX - 10, yStops[i], canvasEndX, yStops[i]);
}
}
public void drawGridText() {
int canvasStartX = this.calculateCanvasStartX();;
int canvasStartY = this.calculateCanvasStartY();;
int stepsX = sizeInnerCanvas[0]/this.gridStep + 1;
int stepsY = sizeInnerCanvas[1]/this.gridStep + 1;
int num; // variable used to calculate and position the current number
textSize(textSizeGrid);
// Draw text for Y Axis
pushMatrix();
translate(canvasStartX-13,canvasStartY+4);
textAlign (RIGHT);
for (int i = 0; i < stepsY; i++) {
num = i*this.gridStep;
if (num % 100 == 0) {
this.fill2(colorGridNumbers2);
} else {
this.fill2(colorGridNumbers);
}
text(""+num, 0, num);
}
popMatrix();
// Draw text for X Axis
pushMatrix();
translate(canvasStartX+4,canvasStartY - 13);
textAlign (LEFT);
rotate(-HALF_PI);
for (int i = 0; i < stepsX; i++) {
num = i*this.gridStep;
if (num % 100 == 0) {
this.fill2(colorGridNumbers2);
} else {
this.fill2(colorGridNumbers);
}
text(""+num, 0, num);
}
popMatrix();
}
// Helper functions
// Uses an array for setting colors. Much handier for this class.
void fill2(int[] colors) {
fill(colors[0], colors[1], colors[2]);
}
void stroke2(int[] colors) {
stroke(colors[0], colors[1], colors[2]);
}
}
class DrawingUtils {
void star(float x, float y, float radius1, float radius2, int npoints) {
float angle = TWO_PI / npoints;
float halfAngle = angle/2.0;
beginShape();
for (float a = 0; a < TWO_PI; a += angle) {
float sx = x + cos(a) * radius2;
float sy = y + sin(a) * radius2;
vertex(sx, sy);
sx = x + cos(a+halfAngle) * radius1;
sy = y + sin(a+halfAngle) * radius1;
vertex(sx, sy);
}
endShape(CLOSE);
}
}
@paulera
Copy link
Author

paulera commented Mar 6, 2017

Changed Integer.toString(num) to ""+num as it is compatible for both Javascript and Java, to work in the online editor and Processing IDE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment