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({
scaling:"fit",
width:1024,
height:768,
color:"lightblue",
outerColor:darker,
allowDefault:true // code pen only needs this it seems with keyboard
});
frame.on("ready", ()=>{
zog("ready from ZIM Frame"); // logs in console (F12 - choose console)
const stage = frame.stage;
const stageW = frame.width;
const stageH = frame.height;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// BOARD
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// the Board() class - not to be confused with the LeaderBoard() class ;-)
// this defaults to isometric but can be used with top view
// or toggled later with board.isometric = false;
const board = new Board({
backgroundColor:grey,
info:data, // from info file made using board.record();
arrows:false, // hide board arrows so can't scroll to see full maze
indicatorBorderColor:silver
}).center();
board.positionBoard(6,6); // start in the middle of the info
board.tiles.tap(e=>{
if (player.moving) return; // moving pieces given moving property
if (path) { // because rolled over already
board.followPath(player, path, null, null, 2); // nudge camera 2
path = null;
} else { // could be tapping or on mobile with no rollover
getPath(true); // see below... true to follow it once found
}
stage.update();
});
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// BOARD ITEMS
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// add a player and key controls
// provide the keys with the allowed data squares
const player = new Person(yellow,silver,brown);
board
.add(player, 6, 6) // can only add() to the board (otherwise use board.info)
.addKeys(player, "arrows", {data:"x"})
.addKeys(player, "wasd", {data:"x"}); // or control something else with wasd
// add a ZIM Emitter to introduce an Orb!
const emitter = new Emitter({
startPaused:true,
obj:[new Rectangle(16,16), new Triangle(20,20,20), new Circle(10)],
random:{color:[blue, green, pink]},
life:1000,
shrink:false,
force:7.5,
gravity:15,
animation:{
time:1000,
props:{scale:3, rotation:{min:100, max:360, negative:true}}
},
angle:{min:-110, max:-70}
}).center();
board.add(emitter,1,1);
emitter.spurt(12);
// Create an Orb that is the final maze destiation
const orb = new Orb({color2:white})
.alp(0)
.animate({
props:{alpha:1},
time:300,
wait:600
});
board.add(orb, 1, 1);
// Place trees on random dark grey squares
// dark squares were given info data of 0
// when making the info - see https://zimjs.com/iso/
loop(board.info, (row, j)=>{
loop(row, (info, i)=>{
if (info.data==0 && rand()>.4) {
// places not to put a tree relative to info (not board)
// there are 6 info array items on all sides of the board
// so 6+3 -1 for using 0 index is where we do not want a tree
// otherwise it sits in front of the orb, etc.
if (
(i==8 && j==8) || // in front of orb
(i==13 && j==13) || // in front of person
(i==11 && j==11) || // behind person
(i==12 && j==6) // on front of score
) return;
// can't use add() for items outside the board
// so just manipulate the info array
// and then will need to board.update()
// to see any changes to the items on the board
info.items.push(new Tree().alp(.9));
info.color = darker;
}
});
});
board.update();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// TIMER AND SCORER
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// set a timer to be positioned isometric left
const timer = new Timer({
time:100,
borderColor:dark,
isometric:"left"
}).loc(27, 231, stage, 0); // .place();
timer.on("complete",()=>{
timer.backing.color = red;
timer.color = white;
stage.update();
});
// set a Scorer to be positioned isometric right
// isometric right gets registration on top right
// this allows the Timer and Scorer to toggle to top view evenly
const scorer = new Scorer({
score:100,
backgroundColor:orange,
borderColor:dark,
isometric:"right"
}).loc(stageW-27, 231, stage, 0); // .place();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NAVIGATION AT BOTTOM
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// const isom = new Button({
// label:"TOP",
// toggle:"ISO",
// corner:0,
// backgroundColor:pink,
// rollBackgroundColor:green,
// shadowBlur:5,
// shadowColor:"rgba(0,0,0,.2)"
// }).loc(465, 703).sca(.5)
// isom.on("mousedown", ()=>{
// // toggle the isometric properties
// // watch out for "left" and "right" values
// // instead of true for timer and scorer (true will give "left")
// zog("hello")
// // board.isometric = !board.isometric;
// // timer.isometric = timer.isometric?false:"left";
// // scorer.isometric = scorer.isometric?false:"right";
// });
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PATH FINDING
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// simple single cost example - see https://zimjs.com/iso for more!
const AI = new EasyStar.js();
AI.setTileCost("x", 0); // nothing
AI.setAcceptableTiles(["x"]); // default lighter grey tile
let pathID;
let ticker;
let path;
board.on("change", ()=>{ // change triggers when rolled over square changes
if (player.moving) return;
getPath(); // just get path - don't go to path with the go parameter true
});
function getPath(go) { // called from change (mouseover) and from tap
AI.setGrid(board.data); // a subset of the info array with only data values
// cancel any previous path and ticker
AI.cancelPath(pathID);
if (ticker) Ticker.remove(ticker);
// if no currentTile then mouse is outside board
if (!board.currentTile) {
board.clearPath();
path = null;
return;
}
// get a path from the player to the currentTile
// currentTile is the selected or highlighted tile
pathID = AI.findPath(
player.boardCol, // any board item has a boardCol prop
player.boardRow,
board.currentTile.boardCol, // any tile has a boardColo prop
board.currentTile.boardRow,
function(thePath) { // the callback function when path is found
path = thePath;
Ticker.remove(ticker);
board.showPath(path);
if (go) { // from a press on the tile
board.followPath(player, path, null, null, 2); // nudge camera 2
path = null;
}
}
);
// must calculate the path in a Ticker
ticker = Ticker.add(()=>{AI.calculate();});
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// COLLECTING AND SCORING
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const leaderBoard = new zim.LeaderBoard({
title:"TREE MAZE",
font:"verdana",
data:"UFU7SM", // see https://zimjs.com/leaderboard/
// note when entering domain for the LeaderBoard
// and you are using the LeaderBoard for codepen examples,
// use the domain for the frame that holds the example
// right click on frame and say view frame source
// and look at domain in the url ofo the browser bar at top
// we have had different domains switch back and forth
// try entering: cdpn.io,s.codepen.io for the domain
backgroundColor:yellow,
colors:{
// sorry for the property names
currentRankBackgroundColor: orange,
currentNameBackgroundColor: orange,
currentScoreBackgroundColor: orange,
currentScoreColor: white
}
});
player.moveEvent = player.on("moving", ()=>{
timeout(50, ()=>{
if (player.boardTile == orb.boardTile) {
player.off("moving", player.moveEvent);
// move orb and particles above player
let playerIndex = player.parent.getChildIndex(player);
emitter.parent.setChildIndex(emitter.particles, playerIndex+1);
orb.parent.setChildIndex(orb, playerIndex+1);
emitter.spurt(12);
orb.animate({
props:{alpha:0},
wait:300,
time:300,
call:()=>{
board.remove(orb);
scorer.score+=timer.time*5;
timer.stop();
frame.allowDefault = false; // messing up LeaderBoard with allowDefault true
timeout(1000, ()=>{
leaderBoard.center().score(scorer.score);
leaderBoard.on("close", ()=>{
zgo("https://zimjs.com/iso/", "_blank");
});
});
stage.update();
}
});
}
})
});
player.on("moved", ()=>{
scorer.score = scorer.score-1;
})
new Label("ZIM GAME MODULE 2 - Board()")
.sca(.6).alp(.6).loc(20,20,stage,0);
// DOCS FOR ITEMS USED
// https://zimjs.com/docs.html?item=Frame
// https://zimjs.com/docs.html?item=Board
// https://zimjs.com/docs.html?item=Person
// https://zimjs.com/docs.html?item=Orb
// https://zimjs.com/docs.html?item=Tree
// https://zimjs.com/docs.html?item=Timer
// https://zimjs.com/docs.html?item=Scorer
// https://zimjs.com/docs.html?item=LeaderBoard
// https://zimjs.com/docs.html?item=Circle
// https://zimjs.com/docs.html?item=Rectangle
// https://zimjs.com/docs.html?item=Triangle
// https://zimjs.com/docs.html?item=Label
// https://zimjs.com/docs.html?item=Button
// https://zimjs.com/docs.html?item=tap
// https://zimjs.com/docs.html?item=animate
// https://zimjs.com/docs.html?item=loop
// https://zimjs.com/docs.html?item=loc
// https://zimjs.com/docs.html?item=alp
// https://zimjs.com/docs.html?item=sca
// https://zimjs.com/docs.html?item=center
// https://zimjs.com/docs.html?item=place
// https://zimjs.com/docs.html?item=Emitter
// https://zimjs.com/docs.html?item=rand
// https://zimjs.com/docs.html?item=timeout
// https://zimjs.com/docs.html?item=zog
// https://zimjs.com/docs.html?item=Ticker
// FOOTER
// call remote script to make ZIM Foundation for Creative Coding icon
createIcon(frame);
stage.update(); // this is needed to show any changes
}); // end ready
Also see: Tab Triggers