This is a snake game variation, creating obstacles with the Processing noise function.
//License:CC BY-NC-SA 4.0
//https://creativecommons.org/licenses/by-nc-sa/4.0/
//Fonts:
//JuliaMono Typeface (by cormullion)
//Kobata (by Ariel Martin Perez)
//www.fontesk.com
PFont mono;
PFont kobata;
Snake snake;
Grid grid;
Table highscore;
boolean lost = false;
int levelno=1;
int points=0;
String playername="";
int state = 0;
//variable parameters
PVector[] foodloc;
int foodamount = 5;//amount of food
int itemsize =12; //size of food and width of snake
int snakelength = 200; //startsize and growth after food uptake
int speed = 1; //speed of snake
int edge; //frame around play area
void setup(){
size(700, 700);
edge = 50;
mono = createFont("JuliaMono-Medium.ttf", 32);
kobata = createFont("Kobata-Regular.otf", 32);
snake = new Snake();
grid = new Grid(itemsize);
}
void draw(){
if (frameCount == 1){
startscreen();
}
background(125);
textFont(mono);
//Top display
textSize(20);
fill(168, 34, 38);
textAlign(LEFT);
text("Level: "+levelno, edge-10, 30);
textAlign(RIGHT);
text("Points: "+points, width-(edge-10), 30);
strokeWeight(20);
stroke(168, 34, 38);
fill(255);
rectMode(CORNER);
rect(edge,edge,float(width-2*edge), float(height-2*edge));
grid.display();
fooddisplay();
snake.display();
snake.move();
snake.collisioncheck();
if (lost == true) {
endl();
}
if (foodloc.length == 0) {
endw();
}
control();
if (frameCount == 1){
startscreen();
}
}
void control(){
if (keyPressed == true && keyCode == DOWN && snake.move.y != -speed){
snake.move.x = 0;
snake.move.y = speed;
}
if (keyPressed == true && keyCode == UP && snake.move.y != speed){
snake.move.x = 0;
snake.move.y = -speed;
}
if (keyPressed == true && keyCode == LEFT && snake.move.x != speed){
snake.move.x = -speed;
snake.move.y = 0;
}
if (keyPressed == true && keyCode == RIGHT && snake.move.x != -speed){
snake.move.x = speed;
snake.move.y = 0;
}
}
void keyPressed() {
if (keyPressed == true && (key == 'C' || key == 'c') && foodloc.length == 0 ){
//start of new level
levelno++;
if (levelno < 4){
grid.limit -= 0.5;
} else {
grid.limit -= 0.25;
}
snake.startcoord();
grid.coordinates();
food();
loop();
}
if (keyPressed == true && (key == 'S' || key == 's' & frameCount == 2)){
loop();
}
if (lost == true && highscore.getInt(4, "Points") < points && key==ENTER || key == RETURN){
state=1;
} else {
if (lost == true){
playername += key;
}
}
if (keyPressed == true && key == 'H' || key =='h' & lost == true){
frameCount = 1;
loop();
}
}
void endl () {
snake.move.x = 0;
snake.move.y = 0;
fill(255);
rectMode(CENTER);
rect (float(width/2),float(height/2), width-(2*edge+20), 150);
textSize(50);
textAlign(CENTER,CENTER);
fill (166,3,19);
text ("Game over", float(width/2), float(height/2)-20);
if (highscore.getInt(4, "Points") < points){
switch(state){
case(0):
textSize(15);
text("Enter your name", float(width/2), float(height/2+20));
text(playername,float(width/2), float(height/2+40));
break;
case(1):
highscore.addRow();
highscore.setString(highscore.getRowCount()-1,"Name", playername);
highscore.setInt(highscore.getRowCount()-1,"Level", levelno);
highscore.setInt(highscore.getRowCount()-1,"Points", points);
highscore.sortReverse("Points");
highscore.removeRow(highscore.getRowCount()-1);
saveTable(highscore, "plhs.csv");
textSize(15);
text("Press h for homescreen",float(width/2), float(height/2+30));
noLoop();
break;
}
} else {
textSize(15);
text("Press h for homescreen",float(width/2), float(height/2+30));
noLoop();
}
}
void endw () {
snake.move.x = 0;
snake.move.y = 0;
fill(255);
rectMode(CENTER);
rect (float(width/2),float(height/2+50), width-(2*edge+20), 250);
textSize(50);
textAlign(CENTER,CENTER);
fill (166,3,19);
text ("Level finished", float(width/2), float(height/2));
textSize(15);
text ("Press c, if you are ready for the next level.", float(width/2), float(height/2+50));
noLoop();
}
void food() {
foodloc = new PVector[0];
PVector f;
boolean ftest = true;
for (int i = 0; foodloc.length < foodamount; i++){
f = new PVector (int(map(random(1),0,1,edge+1.5*itemsize,width-edge-1.5*itemsize)), int(map(random(1),0,1,edge+1.5*itemsize,height-edge-1.5*itemsize)));
//this checks that the food is not on the same coordinate as the walls
for (int k=0; k < grid.walls.length; k++){
if (abs(grid.walls[k].x-f.x) <= itemsize && abs(grid.walls[k].y-f.y) <= itemsize ) {
ftest = false;
k=grid.walls.length-1;
}
}
//this checks that the food is not on the same coordinate as other food
for (int fl=0; fl < foodloc.length; fl++){
if (abs(foodloc[fl].x-f.x) <= itemsize && abs(foodloc[fl].y-f.y) <= itemsize ) {
ftest = false;
fl=foodloc.length-1;
}
}
//only if both tests above do not find a match the new coordinate is added
if (ftest == true){
foodloc = (PVector[])append(foodloc,f);
} else {
ftest = true;
}
}
}
void fooddisplay(){
fill(254,190,20);
rectMode(CENTER);
for (PVector i : foodloc) {
noStroke();
square(i.x,i.y, itemsize);
}
}
void startscreen(){
//reset of variables
lost = false;
levelno=1;
points=0;
playername="";
state = 0;
//start of new games
snake.startcoord();
grid.coordinates();
food();
highscore = loadTable("plhs.csv","header");
highscore.setColumnType("Points", Table.INT);
highscore.setColumnType("Level", Table.INT);
background(255);
fill(168, 34, 38);
textFont(kobata);
textSize(100);
textAlign(CENTER);
text("Perlin Snake", width/2, height/4);
textSize(10);
textFont(mono);
text("Press s to start", width/2, height*6/8);
text("Highscores", width/2, height*9/24);
textSize(20);
textAlign(LEFT);
text("Name", width*5/18, height*11/24);
textAlign(CENTER);
text("Level", width*10/18, height*11/24);
text("Points", width*13/18, height*11/24);
for(int i=0; i < highscore.getRowCount(); i++){
TableRow row = highscore.getRow(i);
textAlign(LEFT);
text(row.getString("Name"), width*5/18, height*12/24+i*20);
textAlign(CENTER);
text(row.getInt("Level"), width*10/18, height*12/24+i*20);
text(row.getInt("Points"), width*13/18, height*12/24+i*20);
}
textAlign(LEFT);
textSize(10);
text("Fonts: \nJuliaMono Typeface (cormullion) \nKobata (Ariel Martin Perez) \nwww.fontesk.com", 50, height*7/8);
noLoop();
}
class Grid {
int gridsize;
float elevation;
float limit = 8; //limit for wall generation 10 = no wall
PVector[] walls;
Grid(int tempgridsize){
gridsize = (width-2*edge)/(tempgridsize);
elevation=0;
}
void coordinates(){
noiseSeed(int(random(100)));
walls = new PVector[0];
PVector w = new PVector(0,0);
//starts at one. because first coordinate should not be 0+edge
//goes to gridize-1 because last values would be already out of boundaries of play area
for (int i=1; i < gridsize-1; i ++) {
for (int j=1; j < gridsize-1; j ++) {
elevation = map(noise (i/1.5,j/1.5),0,1,0,10);
if (elevation > limit){
w = new PVector(i*itemsize+edge+itemsize/2, j*itemsize+edge+itemsize/2);//+itemsize/2 to avoid overlap with edge
//keeps area around snake free
if (w.x < snake.location[0].x-snakelength
||
(w.y < snake.location[0].y-2*itemsize || w.y > snake.location[0].y+2*itemsize)
) {
walls = (PVector[]) append(walls,w);
}
}
}
}
}
void display(){
strokeWeight(itemsize);
stroke(168, 34, 38);
strokeCap(PROJECT);
for (PVector i : walls){
point(i.x,i.y);
}
}
}
class Snake{
PVector[] location;
PVector move = new PVector();
Snake(){
}
void startcoord(){
location = new PVector[snakelength];
move.set(1,0);
location[0] = new PVector (int(map(random(1),0,1,edge+snakelength,3*width/4)),int(map(random(1),0,1,height/4,3*height/4)));
for (int i=1; i < location.length; i++) {
location[i] = new PVector (location[i-1].x-1, location[i-1].y);
}
}
void display(){
noStroke();
fill(23,115,69);
for (PVector i : location) {
rectMode(CENTER);
square(i.x,i.y, itemsize);
}
}
void move() {
if (lost == false){
for (int i=location.length-1; i > 0 ;i--) {
location[i].x = location[i-1].x;
location[i].y = location[i-1].y;
}
location[0].add(move);
}
}
void collisioncheck(){
//wall
if (location[0].x < edge+itemsize || location[0].x > width-(edge+itemsize)) { //strokeWeight wall and background
lost = true;
}
if (location[0].y < edge+itemsize || location[0].y > height-(edge+itemsize)) { //strokeWeight wall and background
lost = true;
}
//snake
for (int i=1; i < location.length; i++) {
if (location[0].x == location[i].x && location[0].y == location[i].y){
lost =true;
}
}
//grid
for (PVector k : grid.walls){
if (k.dist(location[0]) < itemsize*0.75){
lost = true;
}
}
//food
for (int i=0; i < foodloc.length; i++) {
float xd = foodloc[i].dist(location[0]);
if (xd < itemsize*0.75){
location = (PVector[])expand(location,location.length+snakelength);
points++;
for (int k=location.length-1; k > location.length-(snakelength+1) ;k--){
location[k] = new PVector(-100,-100);
}
//remove food
PVector[] foodloctemp;
foodloctemp = new PVector[0];
for (int j = 0; j < foodloc.length; j++){
if(j < i) {
foodloctemp = (PVector[])append(foodloctemp,foodloc[j]);
} else {
if (j > i) {
foodloctemp = (PVector[]) append(foodloctemp,foodloc[j]);
}
}
}
foodloc = foodloctemp;
}
}
}
}