HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URLs added here will be added as <link>
s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import
statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
const frame = new Frame("fit", 800, 600);
frame.on("ready", ()=>{ // ES6 Arrow Function - similar to function(){}
zog("ready from ZIM Frame"); // logs in console (F12 - choose console)
// often need below - so consider it part of the template
let stage = frame.stage;
let stageW = frame.width;
let stageH = frame.height;
frame.outerColor = "#555";
frame.color = "#EEE";
// REFERENCES for ZIM at http://zimjs.com
// see http://zimjs.com/learn.html for video and code tutorials
// see http://zimjs.com/docs.html for documentation
// see https://www.youtube.com/watch?v=pUjHFptXspM for INTRO to ZIM
// see https://www.youtube.com/watch?v=v7OT0YrDWiY for INTRO to CODE
// CODE HERE
var load = frame.loadAssets(["ball.png", "bottle.png"], "https://d309knd7es5f10.cloudfront.net/codepen/");
load.on("complete", ()=>{
// CREATE PHYSICS WORLD
// call the ZIM physics helper class for the Box2D physics engine
// can also set bounds (default the stage) and gravity (default 10)
// see https://d309knd7es5f10.cloudfront.net/physics_1.0.js for Physics Details
// and physics examples in ZIM BITS http://zimjs.com/bits.html
const bounds = {x:0, y:-1000, width:stageW, height:stageH+1000}; // let ball go above the stage
const physics = new Physics(frame, bounds);
// MAKE BALL
// map canvas shapes (visible) to physics shapes (invisible)
// canvas ball
// Box2D objects are all center registration - Bitmaps are by default top left reg - so centerReg()
const ball = frame.asset("ball.png").sca(.6).centerReg().cur();
// physics ball (we add the Body suffix by convention)
// restitution is how bouncy (higher the bouncier)
// angular is angular damping (higher prevents spin)
// there is also linear for linear damping and friction for um... friction
// and there are more options - see https://d309knd7es5f10.cloudfront.net/physics_1.0.js
const ballBody = physics.makeCircle({radius:ball.width/2, restitution:.6, angular:1});
ballBody.x = ball.x;
ballBody.y = ball.y;
physics.addMap(ballBody, ball);
// MAKE SCORE LABEL
var scoreLabel = new Label({
text:0,
size:50,
align:"right",
color:frame.white,
backgroundColor:frame.light
}).pos(stageW-50, 30, stage, 0); // at level 0 under ball
// PRESS ON BALL, KEEP SCORE and CHANGE COUNTRY
// apply force to ball when pressed and keep count
let score = 0;
let min = 250;
let max = 450;
let ballEvent = ball.on("mousedown", (e)=>{ // assign event to variable to remove and add later
scoreLabel.text = ++score; // pre-assignment iterator
let upForce = -rand(min, max);
let sideForce = (ballBody.x-e.stageX)/physics.scale * upForce/(-5);
// first vector is the force, second vector is where to apply the force
// this is a Box2D method (note they start with capital letters - sigh)
// so need to convert distance to meters based on physics scale
ballBody.ApplyImpulse(new b2Vec2(sideForce, upForce), new b2Vec2(e.stageX/physics.scale, e.stageY/physics.scale));
// swap contries
countryLabel.animate({
obj:{alpha:0},
time:400,
rewind:true,
rewindCall:()=>{
countryLabel.text = countries[++countryIndex%countries.length];
countryLabel.scaleTo(stage, 95, 70, "both");
}
});
});
// HANDLE HITTING GROUND and END GAME
// Box2D seems to have no way to remove contact listeners so we use a check variable
// that we set to true when the game is ended and we do not want to check for contact
// when we restart the game, we set the endCheck to false
var endCheck;
ball.on("mousedown", ()=>{
// We can use ZIM HitTests or find the height of the ball in a Ticker, etc. to end the game
// but here we use the Box2D contact listener system - a little awkward but gives solid results
endCheck = false;
let contactListener = new b2ContactListener();
contactListener.BeginContact = function(e) { // gets automatically called every contact
if (endCheck) return; // already ended
// the event object gives us which two body FIXTURES are hitting for ALL hits
// we then need to check if the bodies are the two we are insterested in
// the bottom border wall body is physics.borderBottom and the ball is ballBody
if (
(e.m_fixtureA.GetBody() == ballBody && e.m_fixtureB.GetBody() == physics.borderBottom) ||
(e.m_fixtureA.GetBody() == physics.borderBottom && e.m_fixtureB.GetBody() == ballBody)
) {
// then ball is hitting bottom
endCheck = true;
ball.off("mousedown", ballEvent);
ball.cur("default");
countryLabel.text = "GAME OVER";
countryLabel.scaleTo(stage, 95, 70, "both");
timeout(1000, ()=>{
board.score(score);
boardBacking.addTo();
board.addTo();
});
}
}
// set the contact listener on the world
physics.world.SetContactListener(contactListener);
}, null, true); // run only once!
// MAKE BOTTLE TO PAUSE GAME
const bottle = frame.asset("bottle.png").sca(.4).centerReg().cur();
const bottleBody = physics.makeRectangle({width:bottle.width, height:bottle.height, angular:.8});
bottleBody.x = 70;
bottleBody.y = 100;
physics.addMap(bottleBody, bottle);
// pause ball when press bottle and unpause when press off bottle
bottle.on("mousedown", ()=>{
ballBody.SetType(b2Body.b2_staticBody);
stage.on("stagemousedown", ()=>{
ballBody.SetType(b2Body.b2_dynamicBody);
}, null, true); // remove listener after it runs once
});
// drag the bottle
physics.drag([bottleBody]); // pass in an array of bodies to drag or null to drag all dynamic bodies
// MAKE CONTRIES
const countries = shuffle(["RUSSIA", "BRAZIL", "IRAN", "JAPAN", "MEXICO", "BELGIUM", "SOUTH KOREA", "SAUDI ARABIA", "GERMANY", "ENGLAND", "SPAIN", "NIGERIA", "COSTA RICA", "POLAND", "EGYPT", "ICELAND", "SERBIA", "PORTUGAL", "FRANCE", "URUGUAY", "ARGENTINA", "COLOMBIA", "PANAMA", "SENEGAL", "MOROCCO", "TUNISIA", "SWITZERLAND", "CROATIA", "SWEDEN", "DENMARK", "AUSTRALIA", "PERU"]);
let countryIndex = 0;
const countryLabel = new Label({
text:countries[countryIndex],
size:300,
color:frame.white,
align:"center",
valign:"center",
}).scaleTo(stage, 95, 70, "Both").centerReg(stage, 0);
// MAKE LEADER BOARD
const boardBacking = new Rectangle(stageW, stageH, frame.white).alp(.8).addTo(stage);
boardBacking.on("mousedown", ()=>{
// this starts or restarts the game
board.removeFrom();
boardBacking.removeFrom();
ball.off("mousedown", ballEvent); // remove the ballEvent as we will add it again below
ballEvent = ball.on("mousedown", ballEvent);
// add the first press event to start the game
ball.on("mousedown", ()=>{
endCheck = false;
}, null, true); // only run the first time
ball.cur();
countryLabel.text = countries[countryIndex%countries.length];
countryLabel.scaleTo(stage, 95, 70, "both");
scoreLabel.text = score = 0;
});
// LeaderBoard - see the game module (js file) and http://zimjs.com/leaderboard
const board = new zim.LeaderBoard({
title:"SOCCER UP",
data:"X233C92Q"
})
.siz(null,stageH*.8)
.center();
// physics.debug(); // makes it so you can see physics bodies
// FOOTER
// call remote script to make ZIM Foundation for Creative Coding icon
createIcon(frame);
}); // end asset load
}); // end of ready
Also see: Tab Triggers