xxxxxxxxxx
/*
Enjoy being in the shoes of a wizard or witch and create your own world with magic!
Take a look at my 1st person 3D template to start expirementing creating your own first person game here!:
https://openprocessing.org/sketch/1991810
~~~~~CONTROLS~~~~~
Controls are listed on left side of the sketch now!
Other controls:
Top Right of screen - options that affect the next object you place
obj_color - This button allows you to choose the color of the next object you place
No_Stroke - If you activate this, there will be no stroke displaying on your object
obj_StrkColor - Allows you to chose the stroke color of your object
modulate - If you activate this, your object will switch between black and white
mod_Speed - Allows you to choose the speed your object switches between black and white
MoveXAxis - If activated, your object will move on the X axis
Mouse - Move to look around
Space - Hold to fly straight up
Credits:
First Person Movement code:
Ryan Gilmour - FPS Game (https://openprocessing.org/sketch/1837061)
3D Hands:
https://sketchfab.com/3d-models/fps-arms-5102dc741fcf45ddb33a20091d22e428
3D Wand:
https://sketchfab.com/3d-models/magic-wand-53220e5960e2499ca08c379cd601b62d
Winter skydome
https://sketchfab.com/3d-models/free-skybox-winter-night-9cf1663e9a8647b987ce4f439c22ff50#download
Music:
Music by <a href="https://pixabay.com/users/soundgalleryby-21339672/?utm_source=link-attribution&utm_medium=referral&utm_campaign=music&utm_content=125101">SoundGalleryBy</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=music&utm_content=125101">Pixabay</a>
Jason for suggesting giving the player a wand
*/
let BTMportalx=700
let BTMportalz=-974
let BTMportaly=700
let ClickTimer=false
let clickCounter=0
let buildModeCone=false
let buildModeSphere=false
let buildMode=false
let deleteMode=true
let playerblocknum=0
let SelectorX=0
let SelectorY=0
let SelectorZ=0
let stopFalling=false
let inc=0
let font
let fon
let px=-15
let py=10
let pz=-1
let px2=-15
let py2=10
let pz2=-3
let gravity=.01
function preload()
{
soundFormats('mp3', "wav");
BGmusic = loadSound('xmasmusic.mp3');
arms = loadModel("arms.obj") //load 3D arms
wand = loadModel("wand.obj") //load 3D wand
broom = loadModel("wand.obj") //load 3D broom
skydome = loadImage("winter_night.jpg") //load skydome texture
}
// Camera object for controlling the position, pan and tilt of the camera
let cam =
{
x: 0, y: 0, z: 0,
th: 0, phi: 0.01,
velY:0
}
// Walk speed
let spd = 11;
// Stores the mouse position on the previous frame
let mousePrev =
{
x: 0, y: 0
}
let mouseArray = [mousePrev];
let mousePos;
let lines
function setup()
{
let button = createButton('Instructions'); //positions buttons on screen that acts as instructions - these buttons do nothing
button.position(25, 100);
let button1 = createButton('WASD keys to move');
button1.position(6, 130);
let button2 = createButton('Press 1 - Delete Mode');
button2.position(6, 160);
let button3 = createButton('Press 2 - Box Maker');
button3.position(6, 190);
let button4 = createButton('Press 3 - Sphere Maker');
button4.position(6, 220);
let button5 = createButton('Press 4 - Cone Maker');
button5.position(6, 250);
let button9 = createButton('Left Shift - Sprint/Thrust');
button9.position(6, 280);
let button6 = createButton('Left Click - Action Button');
button6.position(6, 310);
let button7 = createButton('Space Bar - To fly up');
button7.position(6, 340);
let button8 = createButton('P Key - Save Photo');
button8.position(6, 370);
OPC.color('player_color', 'tan'); //native color selector
OPC.color('wand_color', 'brown'); //native color selector
OPC.color('obj_color', '#ffffff'); //creates slider or option tool at top right of screen for user to choose color
OPC.toggle('No_Stroke',false)
OPC.color('obj_StrkColor', 'black')
OPC.toggle('modulate',false)
OPC.slider('mod_Speed',5,0,100,.15)
OPC.toggle('MoveXAxis',false)
pixelDensity(.5) //makes each pixel on screen half size of the default (1) pixel to increase performance
createCanvas(1300, 700, WEBGL); //creates canvas on screen
perspective(PI / 3, width / height, 1, 150000); //used to determine how far player/camera can see - observe by changing last value to 500
mousePrev.x = mouseX - width/2;
mousePrev.y = mouseY*1.5 - height/2 -200;
mousePos = {x: mouseX - width/2, y: mouseY - height/2}
//Creates randomized blocks you see when starting the game
for(i=0;i<2000;i++)
{
eval("blocks"+i+"=createblocks();")
}
}
let mouseUpdate = 0;
let momentum =
{
x: 0,
y: 0
}
let walkShake =
{
z: 0,
x: 0
}
let walk =
{
x: 0,
z: 0
}
function draw()
{
background("skyblue");
let currentMouseX = mousePos.x;
let currentMouseY = mousePos.y;
mousePos.x += ((mouseX-width/2) - currentMouseX) / 10;
mousePos.y += ((mouseY-height/2) - currentMouseY) / 10;
momentum.x += ((mouseX-width/2) - mouseArray[0].x)
momentum.y += ((mouseY-height/2) - mouseArray[0].y)
momentum.x *= 0.9
momentum.y *= 0.9
cam.th += ((mouseX-width/2) - mouseArray[0].x) / 1000;
if(abs((mousePos.y - mousePrev.y) / 100) < PI)
{
cam.phi += ((mouseY-height/2) - mouseArray[0].y) / 1000;
if(abs(cam.phi) > PI/2)
{
cam.phi -= ((mouseY-height/2) - mouseArray[0].y) / 1000;
}
}
if(keyIsDown(49)) //if key number "1" is down/pressed
{
deleteMode=true //activate deleteMode, deactivate every other mode
buildMode=false
buildModeSphere=false
buildModeCone=false
}
if(keyIsDown(50)) //if key number "2" is down/pressed
{
deleteMode=false
buildMode=true //activate buildMode, deactivate every other mode
buildModeSphere=false
buildModeCone=false
}
if(keyIsDown(51)) //if key number "3" is down/pressed
{
deleteMode=false
buildMode=false
buildModeSphere=true //activate buildSphereMode, deactivate every other mode
buildModeCone=false
}
if(keyIsDown(52)) //if key number "4" is down/pressed
{
deleteMode=false
buildMode=false
buildModeSphere=false
buildModeCone=true //activate buildConeMode, deactivate every other mode
}
//ClickTimer is the timer set to go off after a player creates 1 block
//That way the player does not create multiple blocks after one click - a timer is activated after the first block is placed
//to stop this from happening
//Initially the ClickTimer is false/not activated
if(ClickTimer==false)
{
if(mouseIsPressed & buildMode==true) //if mouse pressed and build mode is activated
{
eval("playerBlock"+playerblocknum+"=createPlayerBlock(1);")
playerblocknum++
ClickTimer=true
}
if(mouseIsPressed & buildModeSphere==true) //if mouse pressed and build mode sphere is activated
{
eval("playerBlock"+playerblocknum+"=createPlayerBlock(2);")
playerblocknum++
ClickTimer=true
}
if(mouseIsPressed & buildModeCone==true) //if mouse pressed and build mode cone is activated
{
eval("playerBlock"+playerblocknum+"=createPlayerBlock(3);")
playerblocknum++
ClickTimer=true
}
}
if(ClickTimer==true)
{
clickCounter++
if(clickCounter>=5)
{
clickCounter=0
ClickTimer=false
}
}
// If W is pressed, Move forward
if(keyIsDown(87))
{
if(BGmusic.isPlaying()==false) BGmusic.play() //if background music is not playing, activate it. This also loops the music
cam.x += spd * cos(cam.th)
cam.y += spd * sin(cam.th)
}
// If S is pressed, Move backward
if(keyIsDown(83))
{
cam.x -= spd * cos(cam.th)
cam.y -= spd * sin(cam.th)
}
if(keyIsDown(87) || keyIsDown(83))
{
walk.z += 0.225;
walk.x += 0.225;
walkShake.z = 2 * sin(walk.z)
walkShake.x = 0.3 * sin(walk.x/2)
} else if(keyIsDown(65) || keyIsDown(68))
{
walk.z += 0.225;
walk.x += 0.225;
walkShake.z = 1.65 * sin(walk.z)
walkShake.x = 0.15 * sin(walk.x/2)
}
else
{
walk.x = 0;
walk.z = 0
walkShake.z *= 0.9;
walkShake.x *= 0.9
}
// Strafe left
if(keyIsDown(65))
{
cam.x -= spd * cos(cam.th + PI/2)
cam.y -= spd * sin(cam.th + PI/2)
}
// Strafe right
if(keyIsDown(68))
{
cam.x -= spd * cos(cam.th - PI/2)
cam.y -= spd * sin(cam.th - PI/2)
}
if(stopFalling==false)
{
gravity=1
cam.velY = cam.velY-gravity
cam.z = cam.z + cam.velY;
}
if(cam.z<=100 && cam.z>-1) //cam.z is actually cam.y - the player's y coordinate on screen
{
//applys gravity so player will come down after jumping
gravity=1
}
if (keyIsDown(32))
{ //if space key is down/pressesd
cam.velY=cam.velY+2 //players velocity is decreased, so player can jump
}
//player's point of view
camera(cam.x + walkShake.x*cos(cam.th + PI/2), cam.y + walkShake.x*sin(cam.th + PI/2), cam.z + walkShake.z,
cam.x + 10*cos(cam.phi)*cos(cam.th), cam.y + 10*cos(cam.phi)*sin(cam.th), cam.z + walkShake.z - 10*sin(cam.phi),
0, 0, -1)
push()
translate(cam.x, cam.y, cam.z) //player's position
rotateZ(cam.th - momentum.x / 5000)
rotateY(cam.phi - momentum.y / 5000)
translate(100-85.769, 75-70.436, -100+67.561) //arm position - this data is adjusted off of the previous translate() function. So arms
scale(20) //will always move with player
rotateX(1.58)
rotateY(3.115)
rotateZ(5.9510000000000005)
stroke(player_color)
fill(player_color)
model(arms)
translate(.99-6,.69,.99) //wand position - this data is adjusted off of the previous translate() function
rotateX(2.117)
rotateY(0)
rotateZ(.3546)
noStroke()
scale(3.133)
fill(wand_color)
model(wand)
if(cam.z>=-840) //if player above ground floor, display broom
{
translate(0,.2,.99)
rotateZ(2179.863)
scale(3)
fill(90,39,41)
model(broom)
}
pop()
push()
SelectorX= round((cam.x+100-85.769-6+60*cos(cam.phi)*cos(cam.th)) /50)*50 //gets coordinates for the green selector for the different object placements
SelectorY= round((cam.y+75-70.436+60*cos(cam.phi)*sin(cam.th)) /50)*50
SelectorZ= round((cam.z+-100+67.561-60*sin(cam.phi)+15) /50)*50
translate(SelectorX,SelectorY,SelectorZ) //positions coordinates of green selector
stroke("limegreen")
noFill()
if(buildMode==true) box(50) //box selector
else if(buildModeSphere==true) sphere(25) //sphere selector
else if(buildModeCone==true) //cone selector
{
rotateX(1.57)
cone(25,50)
}
else
{
pop()
push()
SelectorX= round((cam.x+100-85.769-6+60*cos(cam.phi)*cos(cam.th)) /15)*15 //gets coordinates for the green selector for the object deletion box
SelectorY= round((cam.y+75-70.436+60*cos(cam.phi)*sin(cam.th)) /15)*15
SelectorZ= round( (cam.z+-100+67.561-60*sin(cam.phi)+15) /15)*15
translate(SelectorX,SelectorY,SelectorZ)
noFill()
stroke("limegreen")
box(10) //deletion box
}
pop()
mousePrev = {x: mouseX - width/2, y: mouseY - height/2}
mouseArray.push(mousePrev)
if(mouseArray.length > 10)
{
mouseArray.shift()
}
for(i=0;i<2000;i++)
{
eval("updateblocks(blocks"+i+");")
}
for(i=0;i<playerblocknum;i++)
{
eval("updatePlayerBlock(playerBlock"+i+");")
}
//world items
push() //skydome - giant sphere the player is in
translate(0,0,0)
rotateX(4.562)
texture(skydome) //adds image that we see visible in the sphere
noStroke()
sphere(4000)
pop();
push()//xmas tree
translate(1000,0,-675)
fill("green")
noStroke()
rotateX(1.57)
cone(450,450)
translate(0,330,0)
cone(350,350)
translate(0,230,0)
cone(250,250)
pop();
push()//xmas center brown trunk
translate(1000,0,-975)
fill("brown")
box(50,50,1500)
pop()
push()//white floor player can walk on
translate(0,0,-975)
fill(255)
noStroke()
plane(7500)
pop();
//portal
push()//bottom portal
translate(BTMportalx,BTMportaly,BTMportalz)
fill(0,0,random(255))
noStroke()
circle(0,0,500)
pop();
TOPportalx=400
TOPportalz=3900
TOPportaly=400
push()//top portal
translate(TOPportalx,TOPportaly,TOPportalz)
fill(0,0,random(255))
noStroke()
circle(0,0,500)
pop();
let PlayerDistanceFromBottomPortal = dist(cam.x,cam.y,BTMportalx,BTMportaly)
if (PlayerDistanceFromBottomPortal <= 500/2 && cam.z<-905)
{
cam.x=TOPportalx
cam.y=TOPportaly
cam.z=TOPportalz
gravity=1
}
let PlayerDistanceFromTopPortal = dist(cam.x,cam.y,TOPportalx,TOPportaly)
if (PlayerDistanceFromTopPortal <= 500/2 && cam.z>3900)
{
cam.x=BTMportalx
cam.y=BTMportaly
cam.z=BTMportalz
}
//side portals
LEFTportalx=3500
LEFTportalz=1500
LEFTportaly=400
push()//bottom portal
translate(LEFTportalx,LEFTportaly,LEFTportalz)
fill(0,random(255),0)
noStroke()
rotateY(3.14/2)
circle(0,0,500)
pop();
RIGHTportalx=-3500
RIGHTportalz=1500
RIGHTportaly=400
push()//top portal
translate(RIGHTportalx,RIGHTportaly,RIGHTportalz)
fill(0,random(255),0)
noStroke()
rotateY(3.14/2)
circle(0,0,500)
pop();
let PlayerDistanceFromLEFTPortal = dist(cam.x,cam.z,LEFTportalx,LEFTportalz)
if (PlayerDistanceFromLEFTPortal <= 500/2 && cam.x>3500)
{
cam.x=RIGHTportalx
cam.y=RIGHTportaly
cam.z=RIGHTportalz
let choice =round(random(2))
if(choice==0)
{
for(i=0;i<2000;i++)
{
eval("blocks"+i+".r=random(255)")
eval("blocks"+i+".g=0")
eval("blocks"+i+".b=0")
eval("blocks"+i+".size=random(200)")
}
}
if(choice==1)
{
for(i=0;i<2000;i++)
{
eval("blocks"+i+".r=0")
eval("blocks"+i+".g=random(255)")
eval("blocks"+i+".b=0")
eval("blocks"+i+".size=random(200)")
}
}
if(choice==2)
{
for(i=0;i<2000;i++)
{
eval("blocks"+i+".r=0")
eval("blocks"+i+".g=0")
eval("blocks"+i+".b=random(255)")
eval("blocks"+i+".size=random(200)")
}
}
}
let PlayerDistanceFromRIGHTPortal = dist(cam.x,cam.z,RIGHTportalx,RIGHTportalz)
if (PlayerDistanceFromRIGHTPortal <= 500/2 && cam.x<-3500)
{
cam.x=LEFTportalx
cam.y=LEFTportaly
cam.z=LEFTportalz
let choice =round(random(2))
if(choice==0)
{
for(i=0;i<2000;i++)
{
eval("blocks"+i+".r=random(255)")
eval("blocks"+i+".g=0")
eval("blocks"+i+".b=0")
eval("blocks"+i+".size=random(200)")
}
}
if(choice==1)
{
for(i=0;i<2000;i++)
{
eval("blocks"+i+".r=0")
eval("blocks"+i+".g=random(255)")
eval("blocks"+i+".b=0")
eval("blocks"+i+".size=random(200)")
}
}
if(choice==2)
{
for(i=0;i<2000;i++)
{
eval("blocks"+i+".r=0")
eval("blocks"+i+".g=0")
eval("blocks"+i+".b=random(255)")
eval("blocks"+i+".size=random(200)")
}
}
}
if(cam.z<=-905) //if player is right above the floor
{
gravity=0 //we keep player on the floor locking these variables
cam.velY=0
cam.z=-905
if (keyIsDown(32)) //if space key is down/pressesd
{
cam.velY=cam.velY+2 //players velocity is decreased, so player can still jump
}
}
if(keyIsDown(80)) //if key number "P"
{
saveCanvas('MyCoolBuild', 'png');
}
if(keyIsDown(16)) //if shift key down,
{
spd = 31; //increase player speed
}
else spd=11 //else player goes back to default speed
}
function createblocks() //blocks player lands on at start of level
{
let blocks={}
blocks.x = random(-3700,3700) //this is z
blocks.y = random(-3700,3700) //this is x
blocks.z = random(-975,-930)// this is y
blocks.size=50
blocks.display=true
blocks.distanceFromBottomPortal=dist(blocks.x,blocks.y,BTMportalx,BTMportaly)
if (blocks.distanceFromBottomPortal <= 500/2)
{
blocks.display=false
}
let colorChoice=round(random(2)) //randomizes what each box color will be
if(colorChoice==0)
{
//RGB values of a white block
blocks.r=255
blocks.g=255
blocks.b=255
}
if(colorChoice==1)
{
//RGB values of a grey block
blocks.r=200
blocks.g=200
blocks.b=200
}
if(colorChoice==2)
{
//RGB values of a dark grey block
blocks.r=130
blocks.g=130
blocks.b=130
}
return blocks
}
function updateblocks(blocks)
{
if(blocks.display==true)
{
if(deleteMode==true & mouseIsPressed & SelectorZ<blocks.z+30 & SelectorZ>blocks.z-30 & SelectorX>blocks.x-30 & SelectorX<blocks.x+30 & SelectorY>blocks.y-30 & SelectorY<blocks.y+30)
{
blocks.display=false
}
else if(deleteMode==true & SelectorZ<blocks.z+30 & SelectorZ>blocks.z-30 & SelectorX>blocks.x-30 & SelectorX<blocks.x+30 & SelectorY>blocks.y-30 & SelectorY<blocks.y+30)
{
stroke("white")
}
else stroke(0)
if(cam.z<=blocks.z+100 & cam.x>blocks.x-50 & cam.x<blocks.x+50 & cam.y>blocks.y-50 & cam.y<blocks.y+50 ) //if player on block
{
if (keyIsDown(32)) //if space key is down/pressesd
{
cam.velY=cam.velY+2 //players velocity is decreased, so player can jump
}
else //else player walks normally on block
{
gravity=0
cam.velY=0
cam.z=blocks.z+100
}
}
push()
translate(blocks.x,blocks.y,blocks.z)
fill(blocks.r,blocks.g,blocks.b)
box(blocks.size)
pop();
}
}
function createPlayerBlock(mode) //make block placed by player
{
let playerBlock={}
playerBlock.x = SelectorX
playerBlock.y = SelectorY
playerBlock.z = SelectorZ
playerBlock.mode = mode
playerBlock.col=obj_color
playerBlock.StrkCol=obj_StrkColor
playerBlock.modulate=modulate
playerBlock.modSpeed=mod_Speed
playerBlock.No_Stroke=No_Stroke
playerBlock.display=true
playerBlock.countdown=false
playerBlock.counter=0
playerBlock.MoveXAxis=MoveXAxis
playerBlock.Movementcountdown=false
playerBlock.Movementcounter=0
return playerBlock
}
function updatePlayerBlock(playerBlock) //update blocks placed by player
{
if(playerBlock.display==true) //if we are displaying the blocks on screen
{
if(deleteMode==true & mouseIsPressed & SelectorZ<playerBlock.z+30 & SelectorZ>playerBlock.z-30 & SelectorX>playerBlock.x-30 & SelectorX<playerBlock.x+30 & SelectorY>playerBlock.y-30 & SelectorY<playerBlock.y+30)
{ //if box has been selected to be deleted, and clicked on
playerBlock.display=false //no longer display the box
}
else
{
push()
if(playerBlock.MoveXAxis==true)
{
if(playerBlock.Movementcountdown==true) playerBlock.Movementcounter=playerBlock.Movementcounter-5
else playerBlock.Movementcounter=playerBlock.Movementcounter+5
if(playerBlock.Movementcounter>=255) playerBlock.Movementcountdown=true
else if(playerBlock.Movementcounter<=0) playerBlock.Movementcountdown=false
translate(playerBlock.x+playerBlock.Movementcounter,playerBlock.y,playerBlock.z)
}
else translate(playerBlock.x,playerBlock.y,playerBlock.z)
if(playerBlock.modulate==true)
{
if(playerBlock.countdown==true) playerBlock.counter=playerBlock.counter-playerBlock.modSpeed
else playerBlock.counter=playerBlock.counter+playerBlock.modSpeed
if(playerBlock.counter>=255) playerBlock.countdown=true
else if(playerBlock.counter<=0) playerBlock.countdown=false
if(playerBlock.No_Stroke==false)
{
stroke(playerBlock.StrkCol)
}
else noStroke()
fill(playerBlock.counter)
}
else
{
fill(playerBlock.col)
if(playerBlock.No_Stroke==false)
{
stroke(playerBlock.StrkCol)
}
else noStroke()
}
if(playerBlock.mode==1) box(50, 50, 50)
else if(playerBlock.mode==2)
{
sphere(25)
}
else if(playerBlock.mode==3)
{
translate(0,0,0)
rotateX(1.57)
cone(25,50)
}
pop();
}
if(cam.z>=playerBlock.z-50 & cam.z<=playerBlock.z+100 & cam.x>playerBlock.x-50 & cam.x<playerBlock.x+50 & cam.y>playerBlock.y-50 & cam.y<playerBlock.y+50 ) //if player on block
{
if (keyIsDown(32)) //if space key is down/pressesd
{
cam.velY=cam.velY+2 //players velocity is decreased, so player can jump
}
else if(cam.z>playerBlock.z-50) //else player walks normally on block
{
gravity=0
cam.velY=0
cam.z=playerBlock.z+100
}
else
{
gravity=0
cam.velY=0
cam.z=playerBlock.z+100
}
}
}
}