Last active
March 30, 2020 13:19
-
-
Save boxmein/7618661 to your computer and use it in GitHub Desktop.
Processing implementation of a small falling-sand game.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Something relating to a falling sand game | |
// | |
// Usage: | |
// | |
// After opening the Processing IDE, copy it into an empty new sketch. | |
// Just as simple as that. | |
// | |
// | |
// Playing: | |
// | |
// Click to draw. | |
// Right-click to delete. | |
// Scroll up to enlarge the brush. | |
// Scroll down to make the brush smaller. | |
// The right arrow key goes to the "next" element ID. | |
// ( There are two elements: wall (1) and magic-lefty-powder (2) ) | |
// The left arrow key goes to the "previous" element ID. | |
// Space is for pause. | |
// Written by boxmein in 2013. | |
// Use under the terms of the MIT license. | |
import java.util.List; | |
import java.util.ArrayList; | |
import java.util.Random; | |
// | |
// Classes and interfaces | |
// | |
// Element class for defining an element | |
interface Element { | |
int flags = 0; | |
int type = 0; | |
// Ticking method | |
// All reactions and probably more intricate | |
// movement should be performed in here | |
void Update (Particle p, int x, int y, List<Particle> particles, Particle[][] pmap); | |
// Drawing method | |
// Pass index, x, y | |
// Return colour in 0xRRGGBB | |
int Draw (Particle p, int x, int y, Particle[][] pmap); | |
} | |
// Particle class for all the particles on the field | |
class Particle { | |
int x, y, life, flags; | |
int type; | |
// Move a particle to a new place forcefully | |
void moveTo(int x, int y, Particle[][] pmap) { | |
if (x > 0 && x < width && | |
y > 0 && y < height && | |
pmap[x][y] == null) { | |
pmap[this.x][this.y] = null; | |
this.x = x; | |
this.y = y; | |
pmap[x][y] = this; | |
} | |
} | |
// Create a particle | |
public Particle (int x, int y, int type) { | |
this.x = x; | |
this.y = y; | |
this.type = type; | |
} | |
} | |
// Element implementations | |
public class Wall implements Element { | |
void Update (Particle p, int x, int y, List<Particle> parts, Particle[][] pmap) { | |
} | |
int Draw (Particle p, int x, int y, Particle[][] pmap) { | |
return 0xF7F7F7; | |
} | |
} | |
public class Sand implements Element { | |
Random rnd; | |
public Sand () { | |
rnd = new Random(); | |
} | |
void Update (Particle p, int x, int y, List<Particle> ps, Particle[][] pmap) { | |
switch (rnd.nextInt(3)) { | |
case 0: | |
p.moveTo(x+1, y+1, pmap); | |
case 1: | |
p.moveTo(x, y+1, pmap); | |
case 2: | |
p.moveTo(x-1, y+1, pmap); | |
} | |
} | |
int Draw (Particle p, int x, int y, Particle[][] pmap) { | |
return 0xFFFED4; | |
} | |
} | |
// | |
// Constants | |
// | |
// Particle types that exist, two in this case. | |
static final int P_WALL = 1; | |
static final int P_SAND = 2; | |
static final int P_NUM = 3; | |
// all sorts of flags | |
// Movement flags: for no movement, don't add any of those | |
// For custom movement, don't add any of those :D | |
static final int FMOVE_POWDER = 0x01; | |
static final int FMOVE_LIQUID = 0x02; | |
// | |
// Non-constant state | |
// | |
boolean paused = false, drawing = false, deleting = false; | |
int colstate = 0, brushsize = 5, brushstate = P_WALL; | |
List<Particle> particles; | |
List<Element> elements; | |
Particle[][] pmap; | |
void setup () { | |
size(612, 384, P2D); | |
background(0); | |
noStroke(); | |
fill(255, 0, 255); | |
particles = new ArrayList<Particle>(); | |
elements = new ArrayList<Element>(P_NUM); | |
pmap = new Particle[width][height]; | |
// add new elements here for cross-referencing | |
elements.add(0, null); | |
elements.add(P_WALL, new Wall()); | |
elements.add(P_SAND, new Sand()); | |
} | |
void draw () { | |
background(0); | |
// Brushing | |
if (drawing) { | |
for (int sy = (int) - Math.ceil(brushsize/2) ; | |
sy <= Math.floor(brushsize/2) ; sy++) { | |
for (int sx = (int) -Math.ceil(brushsize/2); | |
sx<=Math.floor(brushsize/2); sx++) { | |
if (mouseX+sx > 0 && mouseX+sx < width && | |
mouseY+sy > 0 && mouseY+sy < height) { | |
Particle p = new Particle(mouseX+sx, mouseY+sy, brushstate); | |
particles.add(p); | |
// now the topmost particle in the pmap array | |
pmap[mouseX+sx][mouseY+sy] = p; | |
} | |
} | |
} | |
} | |
// Deleting | |
else if (deleting) { | |
for (int sy = (int) - Math.ceil(brushsize/2) ; | |
sy <= Math.floor(brushsize/2) ; sy++) { | |
for (int sx = (int) -Math.ceil(brushsize/2); | |
sx<=Math.floor(brushsize/2); sx++) { | |
if (mouseX+sx > 0 && mouseX+sx < width && | |
mouseY+sy > 0 && mouseY+sy < height) { | |
if (pmap[mouseX+sx][mouseY+sy] == null) continue; | |
particles.remove(particles.indexOf(pmap[mouseX+sx][mouseY+sy])); | |
pmap[mouseX+sx][mouseY+sy] = null; | |
} | |
} | |
} | |
} | |
// Particle update | |
if (!paused && particles.size() > 0) { | |
for (Particle p : particles) { | |
if (p.type > 0) { | |
elements.get(p.type).Update(p, p.x, p.y, particles, pmap); | |
} | |
} | |
} | |
// Drawing | |
for (int y=0;y<height;y++) { | |
for (int x=0;x<width;x++) { | |
if (pmap[x][y] == null) | |
continue; | |
colstate = elements.get(pmap[x][y].type).Draw(pmap[x][y], x, y, pmap); | |
fill((colstate>>16)&0xFF, (colstate>>8)&0xFF, colstate&0xFF); | |
rect(x, y, 1, 1); | |
} | |
} | |
} | |
void keyPressed () { | |
if (key == CODED) { | |
switch (keyCode) { | |
case UP: | |
break; | |
case DOWN: | |
break; | |
case LEFT: | |
if (brushstate - 1 > 0) | |
brushstate--; | |
break; | |
case RIGHT: | |
if (brushstate + 1 < P_NUM) | |
brushstate++; | |
break; | |
default: | |
break; | |
} | |
} | |
else { | |
switch (key) { | |
case ' ': | |
paused = !paused; | |
break; | |
} | |
} | |
} | |
void mousePressed () { | |
if (mouseButton == LEFT) | |
drawing = true; | |
else if (mouseButton == RIGHT) | |
deleting = true; | |
} | |
void mouseReleased () { | |
if (mouseButton == LEFT) | |
drawing = false; | |
else if (mouseButton == RIGHT) | |
deleting = false; | |
} | |
void mouseWheel (MouseEvent evt) { | |
float e = evt.getAmount(); | |
if (e < 0) | |
brushsize += 2; | |
else if (e > 0 && brushsize-2>1) | |
brushsize -= 2; | |
// Visual indicator of about how large the brush is. | |
stroke(170); | |
fill(0, 0, 0, 0); | |
rect(mouseX-(brushsize/2), | |
mouseY-(brushsize/2), | |
brushsize,brushsize); | |
noStroke(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment