Last active
March 18, 2023 17:47
-
-
Save dermotbalson/6509302 to your computer and use it in GitHub Desktop.
Physics
This file contains 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
--# Notes | |
--This project shows to use some basic physics, from bouncing balls and spinning | |
--rectangles, to the basics of a very simple platform game | |
--HOW TO USE THIS PROJECT | |
--There are a number of tabs at the top. Press on a tab to see its code. | |
--Work through the tabs from left to right, to see the project develop | |
--You can run the code in any of the project tabs, by | |
--1. running the program, and | |
--2. selecting the tab number using the controls at the upper left of the screen | |
--The program will remember your selection after that. | |
--This enables you to work with one tab at a time, make changes and see the effects by running the program | |
--# Main | |
--Main | |
--This code manages which Code tab is run | |
--it remembers your last choice, and if you select a different one, it runs that instead | |
local tabs = {} | |
local fnames = {"setup","draw","touched","collide","orientationChanged","close","restart","keyboard","cleanup"} | |
local fns = {} | |
local tabDesc={} | |
function setup() | |
for k,v in ipairs(fnames) do --store addresses of key event functions | |
fns[v] = _G[v] | |
end | |
LastCode=readProjectData("Code") or 1 --load stored tab number | |
parameter.integer("Choose_a_tab",1,#tabs,LastCode,ShowList) --tab selector | |
parameter.action("Run selected tab", RunCode) | |
RunCode() | |
end | |
function ShowList() | |
output.clear() | |
for i=1,#tabs do | |
print(i,tabDesc[i]) | |
end | |
end | |
--these two functions do all the tab switching magic (thanks to Andrew_Stacey) | |
function localise(n,d) | |
if d then tabDesc[n]=d end | |
local t= {} | |
setmetatable(t,{__index = _G}) | |
--setfenv(2,t) | |
tabs[n] = t | |
return t | |
end | |
--change tabs | |
function RunCode() | |
output.clear() | |
saveProjectData("Code",Choose_a_tab) | |
cleanup() | |
local t = tabs[Choose_a_tab] | |
for k,v in ipairs(fnames) do | |
if t[v] then _G[v] = t[v] else _G[v] = fns[v] end -- overwrite with the new code | |
end | |
setup() | |
end | |
--default empty function to avoid errors for tabs that don't have it | |
function cleanup() | |
end | |
--# Step_1 | |
_ENV = localise(1) --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--create one ball that moves across the screen and feels gravity | |
--but it disappears off the edges! | |
function setup() | |
p = physics.body(CIRCLE,50) --create physics ball, radius 50 pixels | |
p.restitution = .8 --very bouncy | |
--Now give it some velocity (velocity is in pixels per second, ie per 60 redraws) | |
p.linearVelocity = vec2(math.random(100,400),math.random(100,400)) | |
p.x = math.random(60,250) --POSITION it randomly on the screen | |
p.y = math.random(400,600) | |
--choose a random colour for the ball | |
pColor=color(math.random(0,255),math.random(0,255),math.random(0,255),100) | |
print("One ball falling") | |
end | |
function draw() | |
background(220) | |
fill(pColor) | |
ellipse(p.x,p.y,100) --draw ellipse over the physics object, diameter 100 pixels | |
end | |
function cleanup() --get rid of physics object if we switch to another tab | |
p:destroy() | |
end | |
--# Step_2 | |
_ENV = localise(2) --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--add floor and walls for ball to bounce off | |
--- ********* < shows code changes | |
function setup() | |
p = physics.body(CIRCLE,50) --create physics ball, radius 50 pixels | |
p.restitution = .8 --very bouncy | |
--Now give it some velocity (velocity is in pixels per second, ie per 60 redraws) | |
p.linearVelocity = vec2(math.random(100,400),math.random(100,400)) | |
p.x = math.random(60,250) --POSITION it randomly on the screen | |
p.y = math.random(400,600) | |
--choose a random colour for the ball | |
pColor=color(math.random(0,255),math.random(0,255),math.random(0,255),100) | |
--create floor and walls ******************************************* | |
w1 = physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) -----bottom | |
w2 = physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) ---left side | |
w3 = physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) --right side | |
print("One ball bouncing off walls") | |
end | |
function draw() | |
background(220) | |
fill(pColor) | |
ellipse(p.x,p.y,100) --draw ellipse over the physics object, diameter 100 pixels | |
end | |
function cleanup() --get rid of physics object if we switch to another tab | |
p:destroy() | |
w1:destroy() | |
w2:destroy() | |
w3:destroy() | |
end | |
--# Step_3 | |
_ENV = localise(3) --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--add more balls | |
--put code in functions | |
function setup() | |
balls={} -- create table of 5 physics objects ************ | |
for i=1,5 do | |
balls[i]=CreateBall() | |
end | |
CreateWalls() | |
print("Several balls bouncing") | |
end | |
function CreateBall() -- function to create a physics object ********** | |
local p = physics.body(CIRCLE,50) | |
p.restitution = .8 | |
--Now give it some velocity (velocity is in pixels per second, ie per 60 redraws) | |
p.linearVelocity = vec2(math.random(100,400),math.random(100,400)) | |
--POSITION it randomly on the screen | |
p.x = math.random(60,250) | |
p.y = math.random(400,600) | |
p.color=color(math.random(0,255),math.random(0,255),math.random(0,255),100) | |
return p | |
end | |
function CreateWalls() ---create walls ********* | |
w1 = physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) | |
w2 = physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) | |
w3 = physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) | |
end | |
function draw() | |
background(220) | |
pushStyle() | |
fill(255,255,0) | |
for i=1,#balls do | |
fill(balls[i].color) | |
ellipse(balls[i].x,balls[i].y,100) | |
end | |
popStyle() | |
end | |
function cleanup() --get rid of physics objects if we switch to another tab | |
for i=1,#balls do | |
balls[i]:destroy() | |
end | |
balls=nil | |
w1:destroy() | |
w2:destroy() | |
w3:destroy() | |
end | |
--# Step_4 | |
_ENV = localise(4) --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--instead of balls falling to the floor, let's do a tabletop | |
--now the balls are rolling round a table | |
--we do this by simply turning off gravity | |
function setup() | |
balls={} -- create table of 5 physics objects | |
for i=1,5 do | |
balls[i]=CreateBall() | |
end | |
CreateWalls() | |
grav=physics.gravity() --store physics gravity so we can restore it if we switch tabs | |
physics.gravity(0,0) -- turn off gravity ************** | |
print("Balls rolling around table") | |
end | |
function CreateBall() -- function to create a physics object | |
local p = physics.body(CIRCLE,50) | |
p.restitution = .8 | |
--Now give it some velocity (velocity is in pixels per second, ie per 60 redraws) | |
p.linearVelocity = vec2(math.random(100,400),math.random(100,400)) | |
--POSITION it randomly on the screen | |
p.x = math.random(60,250) | |
p.y = math.random(400,600) | |
p.color=color(math.random(0,255),math.random(0,255),math.random(0,255),100) | |
return p | |
end | |
function CreateWalls() ---create walls | |
w1 = physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) | |
w2 = physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) | |
w3 = physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) | |
w4 = physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) --- put in top wall too ********** | |
end | |
function draw() | |
background(220) | |
pushStyle() | |
fill(255,255,0) | |
for i=1,#balls do | |
fill(balls[i].color) | |
ellipse(balls[i].x,balls[i].y,100) | |
end | |
popStyle() | |
end | |
function cleanup() --get rid of physics objects if we switch to another tab | |
for i=1,#balls do | |
balls[i]:destroy() | |
end | |
balls=nil | |
w1:destroy() | |
w2:destroy() | |
w3:destroy() | |
w4:destroy() | |
physics.gravity(grav.x,grav.y) --restore default | |
end | |
--# Step_5 | |
_ENV = localise(5) --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--instead of balls falling to the floor, let's do a tabletop | |
--now the balls are rolling round a table | |
--we do this by simply turning off gravity | |
function setup() | |
rects={} --create table of rectangles ********** | |
w=100 --width | |
h=80 --height | |
for i=1,5 do | |
rects[i]=CreateRect(w,h) | |
end | |
CreateWalls() | |
print("Rectangles spinning") | |
grav=physics.gravity() --store physics gravity so we can restore it if we switch tabs | |
physics.gravity(0,0) -- turn off gravity ************** | |
end | |
function CreateRect(w,h) -- function to create a physics object | |
local p = physics.body(POLYGON,vec2(-w/2,h/2),vec2(-w/2,-h/2),vec2(w/2,-h/2),vec2(w/2,h/2)) | |
p.restitution = .8 | |
--Now give it some velocity (velocity is in pixels per second, ie per 60 redraws) | |
p.linearVelocity = vec2(math.random(100,400),math.random(100,400)) | |
--POSITION it randomly on the screen | |
p.x = math.random(60,250) | |
p.y = math.random(400,600) | |
p.color=color(math.random(0,255),math.random(0,255),math.random(0,255),100) | |
return p | |
end | |
function CreateWalls() ---create walls | |
w1 = physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) | |
w2 = physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) | |
w3 = physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) | |
w4 = physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) --- put in top wall too ********** | |
end | |
function draw() | |
background(220) | |
pushStyle() | |
fill(255,255,0) | |
for i=1,#rects do | |
fill(rects[i].color) | |
local x,y=rects[i].x,rects[i].y | |
pushMatrix() | |
translate(x,y) | |
rotate(rects[i].angle) | |
rect(-w/2,-h/2,w,h) | |
popMatrix() | |
end | |
popStyle() | |
end | |
function cleanup() --get rid of physics objects if we switch to another tab | |
for i=1,#rects do | |
rects[i]:destroy() | |
end | |
rects=nil | |
w1:destroy() | |
w2:destroy() | |
w3:destroy() | |
w4:destroy() | |
physics.gravity(grav.x,grav.y) --restore default | |
end | |
--# Step_6 | |
_ENV = localise(6) --DELETE this line if you copy this code to another project (it is used to manage tab changes) | |
--make a character walk and jump | |
--make it full screen | |
function setup() | |
CreateScene() --set up scene | |
SetupChar() | |
print("A jumping platform game") | |
end | |
function draw() | |
background(220) | |
DrawScene() | |
DrawChar() | |
ShowInstructions() | |
end | |
function SetupChar() | |
char=readImage("Planet Cute:Character Boy") --read in image (change it if you like) | |
ch = physics.body(CIRCLE,char.width/2) --create physics circle, radius = 1/2 height of char | |
ch.x=30 | |
ch.y=floorHeight+100 | |
ch.restitution = .1 --not very bouncy | |
ch.linearVelocity = vec2(0,0) | |
ch.x = WIDTH/2 --POSITION it randomly on the screen | |
ch.y = HEIGHT/2 | |
end | |
function CreateScene() | |
--do floor first | |
floorHeight=50 --floor | |
floor=physics.body(EDGE,vec2(0,floorHeight),vec2(WIDTH,floorHeight)) | |
--now do platforms | |
gap=150 --vertical gap between platforms | |
plat={} | |
plat[1]={x1=150,x2=350,y=floorHeight+gap} | |
plat[2]={x1=300,x2=550,y=floorHeight+2*gap} | |
plat[3]={x1=500,x2=700,y=floorHeight+gap} | |
--create physics objects for platforms | |
for i=1,#plat do | |
plat[i].body=physics.body(EDGE,vec2(plat[i].x1,plat[i].y),vec2(plat[i].x2,plat[i].y)) | |
end | |
--set visible platform depth | |
platDepth=5 --pixels | |
--side walls | |
w1 = physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) ---left side | |
w2 = physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) --right side | |
end | |
function DrawScene() | |
pushStyle() | |
--draw ground as solid rectangle | |
fill(185, 157, 140, 255) | |
rect(0,0,WIDTH,floorHeight) | |
--draw floor on top, as a thick line | |
stroke(62, 121, 181, 255) --line colour | |
strokeWidth(5) --thick line | |
line(0,floorHeight-platDepth,WIDTH,floorHeight-platDepth) | |
--draw platforms | |
fill(62, 121, 181, 255) | |
for i=1,#plat do | |
line(plat[i].x1,plat[i].y-platDepth,plat[i].x2,plat[i].y-platDepth) | |
end | |
popStyle() | |
end | |
function DrawChar() | |
sprite(char,ch.x,ch.y) | |
end | |
function ShowInstructions() | |
--write instructions | |
pushStyle() | |
fill(255,0,0) | |
fontSize(24) | |
textMode(CORNER) | |
text("Touch middle of screen to jump",50,HEIGHT-80) | |
text("Touch left/right of screen to walk",50,HEIGHT-120) | |
text("Touch button at top left of screen for menu controls",50,HEIGHT-160) | |
popStyle() | |
end | |
function touched(touch) | |
if touch.state==BEGAN then | |
if touch.x<WIDTH/3 then --left side - go left | |
ch:applyForce(vec2(-500,0)) | |
elseif touch.x<WIDTH*2/3 then --middle - jump | |
if ch.linearVelocity.y==0 then ch:applyForce(vec2(0,5000)) end | |
else --right side, go right | |
ch:applyForce(vec2(500,0)) | |
end | |
end | |
end | |
function cleanup() --get rid of physics object if we switch to another tab | |
floor:destroy() | |
for i=1,#plat do | |
plat[i].body:destroy() | |
end | |
w1:destroy() | |
w2:destroy() | |
ch:destroy() | |
displayMode(STANDARD) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment