new 3D version with player
cursor steering and Space Bar to jump
// Version: Best version with camera moving around center of boxes (looking at player)
// Documentation:
// Use cursor to run. Space to jump. To jump a wall, jump with Space and immediately use cursor.
// Different cameras would be possible: peasyCam, fixed Camera and player following camera.
// to do :
// splash screen
// treasure (Mondrian collects canvas, brush...) -> next level
// you won / you loose
// nicer player
// camera moved to player at start
// better keys: cursor UP, run, space jump
// follow player cam
// constants
final int UNKNOWN = -1;
final float scale1=10;
// boxes
ArrayList<ClassBox> listBoxes = new ArrayList();
// avg pos of all boxes (center)
PVector averageBoxes;
// ID of the box the player is on
int globalID;
// camera
CameraSimple myCamera=new CameraSimple();
// Player
Player player = new Player( 0.0+110*scale1, -1180, 0.0+111*scale1 );
void setup() {
size(1460, 850, P3D);
surface.setTitle("Mondrian");
makeBaseMap();
avoidClipping();
println("Use cursor to run. Space to jump. To jump a wall, jump with Space and immediately use cursor.");
}//func
void draw() {
background(110);
lights();
manageCamera();
showBoxes();
player.display();
player.move();
keyPressedThroughout();
sePlayerFloor();
// HUD --------------------------------------------
showHUD();
//
}//func
//
// ********************************************************************************
// tab: BaseMap.pde
// set boxes
void makeBaseMap() {
// Left side
//
float x=0;
float y=0; // Z
float height1=0; // y
float w=12; // x size
float h=100; // Z size
float d=600;
listBoxes.add(new ClassBox( 0.0+x*scale1, 0.0+height1, 0.0+y*scale1,
w*scale1, d, h*scale1,
color(0, 0, 255),
0));
// upper left corner
x=-43;
y=0; // Z
height1=0; // y
w=70; // x size
h=int(99); // Z size
d=420;
listBoxes.add(new ClassBox( 0.0+x*scale1, 0.0+height1*scale1, 0.0+y*scale1,
w*scale1, d, h*scale1,
color(255, 0, 0), // RED
1 ));
x=-43; // x
y=144; // Z
height1=0; // y
w=70; // x size
h=200-30+19; // Z size
d=240;
listBoxes.add(new ClassBox( 0.0+x*scale1, 0.0+height1*scale1, 0.0+y*scale1,
w*scale1, d, h*scale1,
color(250, 255, 0), // YELLOW
2 ));
x=88-14;
y=0; // Z
height1=0; // y
w=160-23; // x size
h=80-0; // Z size
d=290;
listBoxes.add(new ClassBox( 0.0+x*scale1, height1, 0.0+y*scale1,
w*scale1, d, h*scale1,
color(255), // WHITE
3));
x=72;
y=140; // Z
height1=0; // y
w=160; // x size
h=200; // Z size
d=50;
listBoxes.add(new ClassBox( 0.0+x*scale1, height1, 0.0+y*scale1,
w*scale1, d, h*scale1,
color(0, 0, 255), // Blue
4));
x=13; // x
y=120; // used as Z
height1=0; // used as y
w=70; // x size
h=100; // Z size
d=440; // y height
listBoxes.add(new ClassBox( x*scale1, height1*scale1, y*scale1,
w*scale1, d, h*scale1,
color(255, 0, 0), //RED
5));
// after definig all:
averageBoxes = new PVector();
for (ClassBox item : listBoxes) {
averageBoxes.add(item.pos);
}
averageBoxes.div(listBoxes.size());
//
}
// ********************************************************************************
// tab: ClassBox.pde
// Class Box
class ClassBox {
//
PVector pos = new PVector(0, 0, 0);
PVector sizeBox = new PVector(0, 0, 0);
color colBox;
int id;
// constr
ClassBox(float x, float y, float z,
float w, float h, float d,
color c_,
int id_) {
//
pos.set(x, y, z);
sizeBox.set(w, h, d);
colBox = c_;
id = id_;
}// constr
void display() {
stroke(0);
fill( colBox);
pushMatrix();
translate(pos.x, pos.y, pos.z);
box (sizeBox.x, sizeBox.y, sizeBox.z);
popMatrix();
}
int playerCheck(float playerposx, float playerposz) {
// gets params player.pos.x, player.pos.z
if (
inside(playerposx, pos.x-sizeBox.x/2.0, pos.x+sizeBox.x/2.0) &&
inside(playerposz, pos.z-sizeBox.z/2.0, pos.z+sizeBox.z/2.0)
) {
return id;
}
// Otherwise
return UNKNOWN;
}
boolean inside(float value, float min, float max) {
return
value > min &&
value < max;
}
//
}//class
//
// ********************************************************************************
// tab: ClassCamera.pde
// Camera Simple
class CameraSimple {
// simple camera wrapper
PVector pos = new PVector(0, 0, 0);
PVector lookAt = new PVector(0, 0, 0);
PVector upVector = new PVector(0, 1, 0);
// no constr ---------------------------------------------
void useValues() {
// apply values - this func must be called at all times
camera (pos.x, pos.y, pos.z,
lookAt.x, lookAt.y, lookAt.z,
upVector.x, upVector.y, upVector.z);
}
void useHighUp() {
//camera test
float x= 111;
float y2=-553;
float y= 111;
pos = new PVector(0.0+x*74, -555, 0.0+y*74);
lookAt = new PVector( x*74 + 13, y2*74 - 0, y*74 - 13);
camera (pos.x, pos.y, pos.z,
lookAt.x, lookAt.y, lookAt.z,
upVector.x, upVector.y, upVector.z);
}
//
}//class
//
// ********************************************************************************
// tab: ClassPlayer.pde
// class Player
class Player {
PVector pos = new PVector(0, 0, 0);
float moveY=0;
float diameter = 40;
boolean jumping=false;
float floorPlayer;
boolean isDead=false;
// constr
Player(float x, float y, float z) {
pos.set(x, y, z);
}// constr
void display() {
noStroke();
fill(210);
pushMatrix();
translate(pos.x, pos.y, pos.z);
sphere (diameter);
translate(2, -diameter, 0);
fill(255, 0, 0);
sphere (diameter/2);
popMatrix();
if (pos.y>1200)
isDead=true;
}
void move() {
// jump
pos.y+=moveY;
moveY++;
if (pos.y>floorPlayer) {
pos.y=floorPlayer;
jumping=false;
}
}
//
}//class
//
// ********************************************************************************
// tab: Inputs.pde
// Inputs
void keyReleased() {
key=0;
}
void keyPressedThroughout() {
// Player steering:
// The function allowed() checks if we run against a wall (simulate move).
// If not allowed, we leave with return.
// ballPosPrev = player.pos.copy();
if (key == CODED) {
// CODED
switch(keyCode) {
case LEFT:
if (!allowed ( player.pos.x-15-player.diameter, player.pos.z ) )
return;
player.pos.x-=15;
break;
case RIGHT:
if (!allowed ( player.pos.x+15+player.diameter, player.pos.z ) )
return;
player.pos.x+=15;
break;
case UP:
if (!allowed ( player.pos.x, player.pos.z -15-player.diameter ) )
return;
player.pos.z-=15;
break;
case DOWN:
if (!allowed ( player.pos.x, player.pos.z + 15 + player.diameter ) )
return;
player.pos.z+=15;
break;
}//switch
}//if CODED
// ----------------------------------------
else {
switch(key) {
case ' ':
// jump with Space Bar
if (player.jumping) // if he is alredy jumping
return; // leave
player.jumping=true;
player.moveY=-14;
break;
}//switch
//
}//else: not CODED
}//func
boolean allowed( float x_, float y_ ) {
// collision when next platform is too high
int testGlobalID=UNKNOWN;
for (ClassBox item : listBoxes) {
int temp=item.playerCheck(x_, y_);
if (temp!=UNKNOWN)
testGlobalID=temp;
}//for
// allowed (NEW platform is the same as the old)
if (testGlobalID==globalID) {
return true;
}
if (testGlobalID==UNKNOWN) {
return true; // allowed
}
// check the height difference
ClassBox testBox = listBoxes.get(testGlobalID); // new box
if (player.pos.y <
testBox.pos.y - testBox.sizeBox.y/2 ) {
return true; // allowed (NEW platform is lower than old -> not a wall)
} // if
// NOT allowed (NEW platform is higher than old -> wall)
return false;
}// func
//
// ********************************************************************************
// tab: Tools.pde
// Tools
void avoidClipping() {
// avoid clipping :
// https://forum.processing.org/two/discussion/4128/quick-q-how-close-is-too-close-why-when-do-3d-objects-disappear
perspective(PI/3.0, (float) width/height, 1, 1000000);
}//func
void showHUD() {
camera();
noLights();
textSize(14);
fill(255);
text("Use cursor to run. Space to jump. To jump a wall, jump with Space and immediately use cursor.",
17, 17);
if (player.isDead) {
fill(255, 0, 0);
textSize(79);
textAlign(CENTER, CENTER);
textMode(SHAPE);
text("You are Dead", width / 2, height /2);
textAlign(LEFT);
}
}
void manageCamera() {
float amt = 1.9;
myCamera.pos = new PVector(lerp( averageBoxes.x, player.pos.x, amt ), -1130, lerp( averageBoxes.z, player.pos.z, amt ));
myCamera.pos.y = -1130;
myCamera.lookAt = player.pos; // averageBoxes; // new PVector( 0, height/2, 0 );
myCamera.useValues();
/*
myCamera.pos = new PVector(640, -2130, 1200);
myCamera.lookAt = new PVector( 0, height/2, 0 );
myCamera.useValues();
*/
}
void showBoxes() {
translate(0, height/2, 0);
globalID = UNKNOWN;
for (ClassBox item : listBoxes) {
item.display();
int temp = item.playerCheck(player.pos.x, player.pos.z);
if (temp!=UNKNOWN)
globalID = temp;
}//for
}
void sePlayerFloor() {
if (globalID != UNKNOWN) {
ClassBox currentBox = listBoxes.get(globalID);
player.floorPlayer =
currentBox.pos.y - currentBox.sizeBox.y/2 - player.diameter ;
}//if
else {
// Dead......
player.floorPlayer = 10000;
}
}
//