add 15 games!!
BIN
badicecream/assets/BadIceCream1_sdk.swf
Normal file
BIN
badicecream/assets/badicecream_splash.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
badicecream/assets/builtins/avmplus.abc
Normal file
BIN
badicecream/assets/builtins/builtin.abc
Normal file
BIN
badicecream/assets/builtins/playerglobal.abcs
Normal file
2753
badicecream/assets/builtins/playerglobal.json
Normal file
BIN
badicecream/bad-ice-cream.png
Normal file
After Width: | Height: | Size: 107 KiB |
163
badicecream/index.html
Normal file
@ -0,0 +1,163 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="#382C2A" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
||||
|
||||
<title>Bad Ice Cream</title>
|
||||
<script src="/js/all.js"></script>
|
||||
<script src="poki.js"></script>
|
||||
<script type="text/javascript" src="./js/loader.js"></script>
|
||||
<script type="text/javascript" src="./js/virtualJoystickSkinMod.js"></script>
|
||||
<script type="text/javascript" src="./preloader/nitromePreloader.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
canvas {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#container {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #9badbe;
|
||||
}
|
||||
|
||||
#splash {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#splash__image {
|
||||
position: absolute;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("assets/badicecream_splash.jpg");
|
||||
visibility: visible;
|
||||
transition: opacity 0.5s;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#progress__root {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#progress__line {
|
||||
width: 0;
|
||||
height: 100%;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="splash__image">
|
||||
<div id="progress__root">
|
||||
<div id="progress__line"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.addEventListener("load", () => {
|
||||
PokiSDK.setDebugTouchOverlayController(true);
|
||||
|
||||
PokiSDK.init()
|
||||
.then(() => {
|
||||
// successfully initialized
|
||||
onPokiInitComplete(false);
|
||||
})
|
||||
.catch(() => {
|
||||
// successfully initialized but the user has adblock
|
||||
onPokiInitComplete(true);
|
||||
});
|
||||
let config;
|
||||
|
||||
config = {
|
||||
key: "bic1",
|
||||
title: "BadIceCream 1",
|
||||
filename: "BadIceCream1_sdk",
|
||||
pokiSDK: true,
|
||||
debugPoki: false,
|
||||
showFPS: false,
|
||||
debug: false,
|
||||
splash: "assets/badicecream_splash.jpg",
|
||||
start: null,
|
||||
width: 550,
|
||||
height: 550,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: "100%",
|
||||
h: "100%",
|
||||
stageScaleMode: null,
|
||||
stageAlign: null,
|
||||
progressParserWeigth: 1,
|
||||
progress: {
|
||||
direction: "lr",
|
||||
back: "#35809e",
|
||||
line: "#070bff",
|
||||
rect: [0.25, 0.65, 0.5, 0.03],
|
||||
},
|
||||
box2dVersion: "none",
|
||||
skipFramesOfScene: null,
|
||||
buttonPokiSDKActions: null,
|
||||
retryButtonIDS: null,
|
||||
retryButtonAction: null,
|
||||
actionOnStop: null,
|
||||
actionWhenRetryButtonEncountered: null,
|
||||
binary: [
|
||||
{
|
||||
name: "BadIceCream1_sdk",
|
||||
path: "assets/BadIceCream1_sdk.swf",
|
||||
size: 1937690,
|
||||
resourceType: "GAME",
|
||||
},
|
||||
],
|
||||
runtime: "js/BadIceCream.js",
|
||||
};
|
||||
|
||||
PokiSDK.setDebug(config.debugPoki);
|
||||
|
||||
Loader.init(config);
|
||||
|
||||
let onPokiInitComplete = (adBlocked) => {
|
||||
PokiSDK.adBlocked = adBlocked;
|
||||
PokiSDK.gameLoadingStart();
|
||||
|
||||
Loader.runGame(
|
||||
(fill) => {
|
||||
PokiSDK.gameLoadingProgress({
|
||||
percentageDone: fill,
|
||||
kbLoaded: 0,
|
||||
kbTotal: 0,
|
||||
fileNameLoaded: "",
|
||||
filesLoaded: 0,
|
||||
filesTotal: 0,
|
||||
});
|
||||
window.nitromePreloaderSetProgress(fill / 1.0);
|
||||
},
|
||||
(instance) => {
|
||||
PokiSDK.gameLoadingFinished();
|
||||
window.nitromePreloaderSetComplete();
|
||||
}
|
||||
);
|
||||
};
|
||||
window.nitromePreloaderInit("bad-ice-cream");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
1
badicecream/js/BadIceCream.js
Normal file
329
badicecream/js/loader.js
Normal file
@ -0,0 +1,329 @@
|
||||
var Loader = (function () {
|
||||
function loadBinary(file, progressEvent = f => f) {
|
||||
const req = new XMLHttpRequest();
|
||||
const isScript = file.path.indexOf(".js") > -1;
|
||||
|
||||
req.addEventListener("progress", e => {
|
||||
const total = e.total || file.size;
|
||||
|
||||
if(!total) {
|
||||
progressEvent(1);
|
||||
return;
|
||||
}
|
||||
|
||||
progressEvent(Math.min(1, e.loaded / total) );
|
||||
});
|
||||
|
||||
req.open("GET", file.path, true);
|
||||
req.responseType = isScript ? "text" : "arraybuffer";
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
req.addEventListener("error", rej);
|
||||
req.addEventListener("load", () => {
|
||||
progressEvent(1);
|
||||
|
||||
if (isScript) {
|
||||
// unsafe
|
||||
//eval(req.response);
|
||||
|
||||
const b = new Blob([req.response], { type: "text/javascript" });
|
||||
// use blob
|
||||
loadScript(URL.createObjectURL(b)).then(() => res(undefined));
|
||||
|
||||
return;
|
||||
}
|
||||
res({
|
||||
meta: file.meta || {},
|
||||
name: file.name,
|
||||
path: file.path,
|
||||
resourceType: file.resourceType,
|
||||
data: req.response,
|
||||
type: isScript ? "js" : "swf",
|
||||
});
|
||||
});
|
||||
|
||||
req.send();
|
||||
});
|
||||
}
|
||||
|
||||
function loadScript(file, progress) {
|
||||
const head = document.querySelector("head");
|
||||
const script = document.createElement("script");
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
Object.assign(script, {
|
||||
type: "text/javascript",
|
||||
async: true,
|
||||
src: file.path || file,
|
||||
onload: () => {
|
||||
progress && progress(1);
|
||||
res(script);
|
||||
},
|
||||
onerror: rej,
|
||||
onreadystatechange: s => {
|
||||
if (script.readyState == "complete") { }
|
||||
},
|
||||
});
|
||||
|
||||
head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
function createReporter(callback, childs, weight) {
|
||||
const reporter = {
|
||||
callback: callback,
|
||||
childs: childs ? childs.slice() : undefined,
|
||||
value: 0,
|
||||
weight: weight || 1,
|
||||
|
||||
get report() {
|
||||
return function (v) {
|
||||
if (!this.childs) {
|
||||
this.value = v * this.weight;
|
||||
} else {
|
||||
let summ = 0;
|
||||
let v = 0;
|
||||
|
||||
this.childs.forEach((e) => {
|
||||
summ += e.weight || 1;
|
||||
v += (e.value || 0);
|
||||
});
|
||||
|
||||
this.value = v / summ;
|
||||
}
|
||||
|
||||
this.callback && this.callback(this.value);
|
||||
}.bind(this);
|
||||
},
|
||||
};
|
||||
|
||||
if (childs) {
|
||||
childs.forEach(e => {
|
||||
e.callback = reporter.report;
|
||||
});
|
||||
}
|
||||
|
||||
return reporter;
|
||||
}
|
||||
|
||||
function runLoadingProcess(jsFiles, binaryFiles, progressEvent = f => f, _debugScripts) {
|
||||
const jsCount = jsFiles.length;
|
||||
const binCount = binaryFiles.length;
|
||||
|
||||
const all = jsFiles.concat(binaryFiles);
|
||||
|
||||
const reporters = Array.from({ length: jsCount + binCount }, () => createReporter());
|
||||
createReporter(progressEvent, reporters);
|
||||
|
||||
let pendings;
|
||||
|
||||
if (!_debugScripts) {
|
||||
pendings = all.map((e, i) => loadBinary(e, reporters[i].report));
|
||||
} else {
|
||||
pendings = binaryFiles.map((e, i) => loadBinary(e, reporters[i].report))
|
||||
pendings = pendings.concat(jsFiles.map((e, i) => loadScript(e, reporters[i + binCount].report)))
|
||||
}
|
||||
|
||||
return Promise.all(pendings).then(data => {
|
||||
return data.filter(e => e && e.type === 'swf');
|
||||
});
|
||||
}
|
||||
|
||||
let fillLine = undefined;
|
||||
let __config = undefined;
|
||||
let __splash = undefined;
|
||||
let __pr__root = undefined;
|
||||
let handleResize = undefined;
|
||||
|
||||
window["setStageDimensions"]=function(x, y, w, h){
|
||||
__config.x=x;
|
||||
__config.y=y;
|
||||
__config.w=w;
|
||||
__config.h=h;
|
||||
if(window["AVMPlayerPoki"]){
|
||||
window["AVMPlayerPoki"].setStageDimensions(x, y, w, h);
|
||||
}
|
||||
if(handleResize){
|
||||
handleResize();
|
||||
}
|
||||
}
|
||||
|
||||
function runGame(progressEvent = f => f, completeEvent = f => f) {
|
||||
|
||||
if (!__config) {
|
||||
init();
|
||||
}
|
||||
|
||||
let jss = Array.isArray(__config.runtime) ? jss : [__config.runtime];
|
||||
jss = jss.map(e => ({ path: e.path || e, size: e.size || 0 }));
|
||||
|
||||
const bins = __config.binary;
|
||||
|
||||
const loadReporter = createReporter(null, null, 4);
|
||||
const avmReporter = createReporter((f) => {
|
||||
console.log('AVM Load', f);
|
||||
}, null, __config.progressParserWeigth ? __config.progressParserWeigth : 0.001);
|
||||
|
||||
createReporter(function (fill) {
|
||||
fillLine(fill);
|
||||
// rereport
|
||||
progressEvent(fill);
|
||||
}, [loadReporter, avmReporter])
|
||||
|
||||
const complete = f => {
|
||||
// rereport
|
||||
completeEvent(f);
|
||||
|
||||
if (__config.start) {
|
||||
|
||||
// start image exists.
|
||||
// hide progressbar, show startimage and wait for user-input to start the game
|
||||
|
||||
Object.assign(__pr__root.style, {
|
||||
visibility: "hidden",
|
||||
opacity: 0,
|
||||
});
|
||||
Object.assign(__splash, { backgroundImage: `url(${__config.start})` });
|
||||
let onCLick = (e) => {
|
||||
window.removeEventListener("click", onCLick);
|
||||
Object.assign(__splash.style, {
|
||||
visibility: "hidden",
|
||||
opacity: 0,
|
||||
});
|
||||
if (!f)
|
||||
throw ("PokiPlayer did not send a callback for starting game");
|
||||
f();
|
||||
window.setTimeout(()=>{
|
||||
window.removeEventListener("resize", handleResize);
|
||||
handleResize=null;
|
||||
}, 500)
|
||||
};
|
||||
window.addEventListener("click", onCLick);
|
||||
}
|
||||
else {
|
||||
// no start image.
|
||||
// game will be started automatically
|
||||
Object.assign(__splash.style, {
|
||||
visibility: "hidden",
|
||||
opacity: 0,
|
||||
});
|
||||
// use Timeout, so css transition can complete first
|
||||
window.setTimeout(()=>{
|
||||
window.removeEventListener("resize", handleResize);
|
||||
handleResize=null;
|
||||
}, 500)
|
||||
}
|
||||
};
|
||||
|
||||
runLoadingProcess(jss, bins, loadReporter.report, __config.debug).then(data => {
|
||||
const runner = window["startPokiGame"];
|
||||
if (!runner) {
|
||||
throw "Could not find a 'startPokiGame' method";
|
||||
}
|
||||
|
||||
__config.files = data;
|
||||
|
||||
runner(__config);
|
||||
|
||||
// now poki player is available at window["AVMPlayerPoki"]
|
||||
// can be used to update the stageDimensions:
|
||||
// window["AVMPlayerPoki"].setStageDimensions(x, y, w, h);
|
||||
// values can be
|
||||
// numbers (absolute pixel values)
|
||||
// strings (percentage of window.innerHeight/innerWidth in 0-100)
|
||||
});
|
||||
|
||||
// make functions avilailable on window, so the loaded js-code can access and execute them
|
||||
Object.assign(window, {
|
||||
updatePokiProgressBar: avmReporter.report,
|
||||
pokiGameParseComplete: complete,
|
||||
});
|
||||
}
|
||||
|
||||
function init(config) {
|
||||
if (!config) {
|
||||
throw new Error("Config is required");
|
||||
}
|
||||
|
||||
__config = config;
|
||||
|
||||
const splash = document.querySelector("#splash__image");
|
||||
const pr__root = document.querySelector("#progress__root");
|
||||
const pr__line = document.querySelector("#progress__line");
|
||||
|
||||
__splash = splash;
|
||||
__pr__root = pr__root;
|
||||
|
||||
const pr_conf = config.progress;
|
||||
pr_conf.rect = pr_conf.rect || [0, 0.9, 1, 0.2];
|
||||
|
||||
Object.assign(splash.style, {
|
||||
backgroundImage: `url(${config.splash})`,
|
||||
visibility: "visible",
|
||||
});
|
||||
|
||||
Object.assign(pr__root.style, {
|
||||
background: pr_conf.back,
|
||||
left: `${100 * pr_conf.rect[0]}%`,
|
||||
top: `${100 * pr_conf.rect[1]}%`,
|
||||
width: `${100 * pr_conf.rect[2]}%`,
|
||||
height: `${100 * pr_conf.rect[3]}%`,
|
||||
});
|
||||
|
||||
Object.assign(pr__line.style, {
|
||||
background: pr_conf.line,
|
||||
});
|
||||
|
||||
fillLine = fill => {
|
||||
switch (pr_conf.direction) {
|
||||
case "tb": {
|
||||
Object.assign(pr__line.style, {
|
||||
height: `${fill * 100}%`,
|
||||
width: "100%",
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "lr":
|
||||
default: {
|
||||
Object.assign(pr__line.style, {
|
||||
height: "100%",
|
||||
width: `${fill * 100}%`,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleResize = () => {
|
||||
let x=(typeof config.x==="string")?parseFloat(config.x.replace("%", ""))/100*window.innerWidth:config.x;
|
||||
let y=(typeof config.y==="string")?parseFloat(config.y.replace("%", ""))/100*window.innerHeight:config.y;
|
||||
let w=(typeof config.w==="string")?parseFloat(config.w.replace("%", ""))/100*window.innerWidth:config.w;
|
||||
let h=(typeof config.h==="string")?parseFloat(config.h.replace("%", ""))/100*window.innerHeight:config.h;
|
||||
|
||||
if(!x) x=0;
|
||||
if(!y) y=0;
|
||||
if(!w) w=window.innerWidth;
|
||||
if(!h) h=window.innerHeight;
|
||||
|
||||
const minMax = Math.min(h / config.height, w / config.width);
|
||||
const rw = Math.ceil(config.width * minMax);
|
||||
const rh = Math.ceil(config.height * minMax);
|
||||
const rx = x+(w - rw) / 2;
|
||||
const ry = y+(h - rh) / 2;
|
||||
|
||||
Object.assign(splash.style, {
|
||||
width: `${rw}px`,
|
||||
height: `${rh}px`,
|
||||
left: `${rx}px`,
|
||||
top: `${ry}px`,
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
handleResize();
|
||||
}
|
||||
|
||||
return {
|
||||
init,
|
||||
runGame,
|
||||
};
|
||||
})();
|
308
badicecream/js/virtualJoystickSkinMod.js
Normal file
@ -0,0 +1,308 @@
|
||||
const isMobile = /Mobi|Android/i.test(navigator.userAgent);
|
||||
if(!isMobile){
|
||||
window.addEventListener('load', ()=>{
|
||||
document.body.style.backgroundImage = 'url(./skin/poki-nitrome_border.png)';
|
||||
document.body.style.backgroundSize = 'cover';
|
||||
document.body.style.backgroundPosition = 'center';
|
||||
});
|
||||
}
|
||||
|
||||
(function (){
|
||||
var scope = {};
|
||||
|
||||
scope.skinnerObject = null;
|
||||
scope.target = null;
|
||||
scope.edgeLeft = null;
|
||||
scope.edgeRight = null;
|
||||
scope.logo = null;
|
||||
scope.home = null;
|
||||
scope.pauseBut = null;
|
||||
scope.pokiLogo = null;
|
||||
scope.frameConfig = {width:480, height:480};
|
||||
scope.portraitOffset = 0;
|
||||
scope.isOnPoki = new URLSearchParams(window.location.search).has('tag');
|
||||
|
||||
scope.getPortraitOffset = function(){
|
||||
const landscape = window.innerWidth > window.innerHeight;
|
||||
const aspect = window.innerWidth/window.innerHeight;
|
||||
const isIpad = (!landscape && aspect >= 0.75) || (landscape && aspect <= 1.34);
|
||||
|
||||
if(landscape){
|
||||
scope.portraitOffset = 0;
|
||||
window["setStageDimensions"](0, 0, "100%", "100%");
|
||||
}else{
|
||||
|
||||
if(isIpad){
|
||||
const frameHeight = window.innerWidth;
|
||||
const gap = (window.innerHeight-frameHeight)/2;
|
||||
scope.portraitOffset = -(gap-gap*(0.5/3));
|
||||
window["setStageDimensions"](0, scope.portraitOffset, "100%", "100%");
|
||||
}else{
|
||||
const frameHeight = window.innerWidth;
|
||||
const gap = (window.innerHeight-frameHeight)/2;
|
||||
scope.portraitOffset = -(gap-gap*(2/3));
|
||||
window["setStageDimensions"](0, scope.portraitOffset, "100%", "100%");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scope.placeSprites = function(){
|
||||
scope.edgeLeft = scope.target.domElement.parentNode.appendChild(scope.createTile(scope.skinnerObject.sprites['edge.png']));
|
||||
scope.edgeRight = scope.target.domElement.parentNode.appendChild(scope.createTile(scope.skinnerObject.sprites['edge.png']));
|
||||
|
||||
scope.logo = scope.target.domElement.parentNode.appendChild(scope.skinnerObject.createImage(scope.skinnerObject.sprites['nitrome_small.png']));
|
||||
scope.logo.style.pointerEvents = 'all';
|
||||
scope.logoPresses = 0;
|
||||
scope.logo.addEventListener('touchstart', ()=>{
|
||||
|
||||
scope.logoPresses++;
|
||||
|
||||
if(scope.logoReleaseTimeout) clearTimeout(scope.logoReleaseTimeout);
|
||||
scope.logoReleaseTimeout = setTimeout(()=>{
|
||||
scope.logoPresses = 0;
|
||||
}, 1000);
|
||||
|
||||
if(scope.logoPresses === 3){
|
||||
const gameboySkin = 'sepia(1) hue-rotate(20deg) brightness(0.65) saturate(0.9)';
|
||||
document.documentElement.style.transition = 'filter 0.5s cubic-bezier(.96,.29,.83,.67) 0s';
|
||||
if(document.documentElement.style.filter === gameboySkin) document.documentElement.style.filter = 'unset';
|
||||
else document.documentElement.style.filter = gameboySkin;
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
if(!scope.isOnPoki){
|
||||
scope.home = scope.target.domElement.parentNode.appendChild(scope.skinnerObject.createImage(scope.skinnerObject.sprites['home.png']));
|
||||
scope.home.style.pointerEvents = 'all';
|
||||
scope.home.style.touchAction = 'none';
|
||||
|
||||
scope.home.ontouchstart = ()=>{
|
||||
scope.home.src = scope.skinnerObject.sprites['home_down.png'];
|
||||
}
|
||||
scope.home.ontouchend = ()=>{
|
||||
scope.home.src = scope.skinnerObject.sprites['home.png'];
|
||||
window.history.back();
|
||||
}
|
||||
}
|
||||
|
||||
scope.pauseBut = document.createElement('div');
|
||||
scope.pauseBut.style.visibility = 'hidden';
|
||||
scope.pauseBut.style.position = 'absolute';
|
||||
scope.target.domElement.parentNode.appendChild(scope.pauseBut);
|
||||
const pauseButtonImage = scope.skinnerObject.createImage(scope.skinnerObject.sprites['pause.png']);
|
||||
pauseButtonImage.style.transform = 'unset';
|
||||
pauseButtonImage.onload = ()=>{
|
||||
scope.pauseBut.style.width = `${pauseButtonImage.width}px`;
|
||||
scope.pauseBut.style.height = `${pauseButtonImage.height}px`;
|
||||
scope.pauseBut.style.visibility = 'visible';
|
||||
}
|
||||
scope.pauseBut.appendChild(pauseButtonImage);
|
||||
scope.pauseBut.style.pointerEvents = 'all';
|
||||
scope.pauseBut.style.touchAction = 'none';
|
||||
scope.pauseBut.ontouchstart = ()=>{
|
||||
scope.target.triggerKeyEvent('keydown', 'P'.charCodeAt(0));
|
||||
setTimeout(()=>{scope.target.triggerKeyEvent('keyup', 'P'.charCodeAt(0))}, 50);
|
||||
|
||||
pauseButtonImage.src = scope.skinnerObject.sprites['pause_down.png'];
|
||||
}
|
||||
scope.pauseBut.ontouchend = ()=>{
|
||||
pauseButtonImage.src = scope.skinnerObject.sprites['pause.png'];
|
||||
}
|
||||
|
||||
scope.pokiLogo = scope.target.domElement.parentNode.appendChild(scope.skinnerObject.createImage(scope.skinnerObject.sprites['poki_large.png']));
|
||||
scope.pokiLogo.style.transform = 'unset';
|
||||
scope.pokiLogo.style.bottom = '6px';
|
||||
scope.pokiLogo.style.right = '6px';
|
||||
}
|
||||
|
||||
scope.resize = function(){
|
||||
const landscape = window.innerWidth > window.innerHeight;
|
||||
|
||||
|
||||
const aspect = window.innerWidth / window.innerHeight;
|
||||
|
||||
const isIpad = (!landscape && aspect >= 0.75) || (landscape && aspect <= 1.34);
|
||||
const edgeSize = 9;
|
||||
scope.getPortraitOffset();
|
||||
const topItemsMargin = 20;
|
||||
|
||||
//have to reset the bounding rect after every repositioning
|
||||
scope.target.virtualJoystick.boundingRect = null;
|
||||
|
||||
|
||||
const preloader = document.querySelector('#nitrome-preloader');
|
||||
|
||||
scope.pokiLogo.src = scope.skinnerObject.sprites['poki_large.png'];
|
||||
|
||||
|
||||
|
||||
if(landscape){
|
||||
const frameWidth = window.innerHeight;
|
||||
const gap = (window.innerWidth-frameWidth)/2;
|
||||
|
||||
scope.edgeLeft.style.left = `${gap}px`;
|
||||
scope.edgeLeft.style.top = `0px`;
|
||||
scope.edgeLeft.style.height = `${window.innerHeight}px`;
|
||||
scope.edgeLeft.style.width = `${edgeSize}px`
|
||||
scope.edgeLeft.style.transform = 'translate(-100%, 0%)';
|
||||
|
||||
scope.edgeRight.style.left = `${gap+frameWidth}px`;
|
||||
scope.edgeRight.style.top = `0px`;
|
||||
scope.edgeRight.style.height = `${window.innerHeight}px`;
|
||||
scope.edgeRight.style.width = `${edgeSize}px`
|
||||
scope.edgeRight.style.transform = 'translate(0%, 0%) rotateZ(180deg)';
|
||||
|
||||
scope.logo.src = scope.skinnerObject.sprites['nitrome_small.png'];
|
||||
|
||||
scope.logo.style.left = `unset`;
|
||||
|
||||
if(!isIpad){
|
||||
scope.logo.style.top = `${topItemsMargin}px`;
|
||||
scope.logo.style.right = `${topItemsMargin*2.3}px`;
|
||||
scope.logo.style.transform = 'translate(-100%, 10%)';
|
||||
}else{
|
||||
scope.logo.style.top = `${topItemsMargin*2}px`;
|
||||
scope.logo.style.right = `${topItemsMargin}px`;
|
||||
scope.logo.style.transform = 'translate(-6%, 100%)';
|
||||
}
|
||||
|
||||
if(scope.home){
|
||||
scope.home.style.top = scope.home.style.left = `${topItemsMargin}px`;
|
||||
scope.home.style.transform = 'unset';
|
||||
}
|
||||
|
||||
scope.pauseBut.style.top = scope.pauseBut.style.right = `${topItemsMargin}px`;
|
||||
scope.pauseBut.style.left = `unset`;
|
||||
scope.pauseBut.style.transform = 'unset';
|
||||
|
||||
scope.skinnerObject.joystickElement.style.left = `${gap/2-edgeSize/2}px`;
|
||||
scope.skinnerObject.joystickElement.style.top = `unset`;
|
||||
scope.skinnerObject.joystickElement.style.bottom = `80px`;
|
||||
|
||||
scope.skinnerObject.buttonsElement.style.left = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.right = `${gap/2-edgeSize/2}px`;
|
||||
scope.skinnerObject.buttonsElement.style.top = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.bottom = `80px`;
|
||||
scope.skinnerObject.buttonsElement.style.paddingLeft = 'unset';
|
||||
|
||||
if(preloader){
|
||||
preloader.style.top = `${window.innerHeight/2}px`;
|
||||
}
|
||||
|
||||
if(isIpad){
|
||||
scope.pokiLogo.src = scope.skinnerObject.sprites['poki_small.png'];
|
||||
}
|
||||
|
||||
}else{
|
||||
const frameHeight = window.innerWidth;
|
||||
const gap = (window.innerHeight-frameHeight)/2;
|
||||
|
||||
scope.edgeLeft.style.left = `${window.innerWidth/2}px`;
|
||||
scope.edgeLeft.style.top = `${gap-edgeSize/2+scope.portraitOffset}px`;
|
||||
scope.edgeLeft.style.width = `${edgeSize}px`
|
||||
scope.edgeLeft.style.height = `${window.innerWidth}px`;
|
||||
scope.edgeLeft.style.transform = 'translate(-50%, -50%) rotateZ(90deg)';
|
||||
|
||||
scope.edgeRight.style.left = `${window.innerWidth/2}px`;
|
||||
scope.edgeRight.style.top = `${gap+frameHeight+edgeSize/2+scope.portraitOffset}px`;
|
||||
scope.edgeRight.style.width = `${edgeSize}px`
|
||||
scope.edgeRight.style.height = `${window.innerWidth}px`;
|
||||
scope.edgeRight.style.transform = 'translate(-50%, -50%) rotateZ(-90deg)';
|
||||
|
||||
scope.logo.src = scope.skinnerObject.sprites['nitrome_full.png'];
|
||||
if(!isIpad){
|
||||
scope.logo.style.bottom = 'unset'
|
||||
scope.logo.style.top = `${-scope.portraitOffset-edgeSize/2}px`;
|
||||
}else{
|
||||
scope.logo.style.bottom = `6px`;
|
||||
scope.logo.style.top = `unset`;
|
||||
}
|
||||
scope.logo.style.right = `unset`;
|
||||
scope.logo.style.left = `${window.innerWidth/2}px`;
|
||||
scope.logo.style.transform = 'translate(-50%, -50%)';
|
||||
|
||||
if(scope.home){
|
||||
if(!isIpad){
|
||||
scope.home.style.bottom = 'unset';
|
||||
scope.home.style.top = `${-scope.portraitOffset-edgeSize/2}px`;
|
||||
scope.home.style.left = `${topItemsMargin}px`;
|
||||
scope.home.style.transform = 'translate(0%, -50%)';
|
||||
}else{
|
||||
scope.home.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
scope.home.style.top = `unset`;
|
||||
scope.home.style.left = `${window.innerWidth/2 - topItemsMargin*1.5}px`;
|
||||
scope.home.style.transform = 'translate(-50%, 50%)';
|
||||
}
|
||||
}
|
||||
|
||||
if(!isIpad){
|
||||
scope.pauseBut.style.bottom = 'unset';
|
||||
scope.pauseBut.style.top = `${-scope.portraitOffset-edgeSize/2}px`;
|
||||
scope.pauseBut.style.right = `${topItemsMargin}px`;
|
||||
scope.pauseBut.style.transform = 'translate(0%, -50%)';
|
||||
}else{
|
||||
scope.pauseBut.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
scope.pauseBut.style.top = `unset`;
|
||||
scope.pauseBut.style.right = `${window.innerWidth/2 - topItemsMargin*1.5}px`;
|
||||
scope.pauseBut.style.transform = 'translate(50%, 50%)';
|
||||
}
|
||||
|
||||
if(!isIpad){
|
||||
scope.skinnerObject.joystickElement.style.left = `30%`;
|
||||
}else{
|
||||
scope.skinnerObject.joystickElement.style.left = `15%`;
|
||||
}
|
||||
scope.skinnerObject.joystickElement.style.top = `unset`;
|
||||
scope.skinnerObject.joystickElement.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
|
||||
if(!isIpad){
|
||||
scope.skinnerObject.buttonsElement.style.right = `26%`;
|
||||
}else{
|
||||
scope.skinnerObject.buttonsElement.style.right = `14%`;
|
||||
}
|
||||
scope.skinnerObject.buttonsElement.style.left = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.top = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
|
||||
if(preloader){
|
||||
preloader.style.top = `${window.innerHeight/2+scope.portraitOffset}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
scope.createTile = function(src){
|
||||
const image = document.createElement('div');
|
||||
image.style.background = `url(${src})`;
|
||||
image.style.position = 'absolute';
|
||||
image.style.transform = 'translate(-50%, -50%)';
|
||||
return image;
|
||||
}
|
||||
scope.init = function(){
|
||||
document.addEventListener('tOCParsed', function(e){
|
||||
const tryToInit = ()=>{
|
||||
try{
|
||||
scope.skinnerObject = e.skinner;
|
||||
scope.target = scope.skinnerObject.target;
|
||||
scope.getPortraitOffset();
|
||||
scope.placeSprites();
|
||||
window.addEventListener('resize', scope.resize);
|
||||
scope.resize();
|
||||
|
||||
if(scope.portraitOffset === 0){
|
||||
// [iOS] Fix initial resizing not going well
|
||||
setTimeout(()=>{
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
},
|
||||
3000)
|
||||
}
|
||||
}catch(e){
|
||||
console.log(e, "FAILED INIT");
|
||||
setTimeout(() => {
|
||||
tryToInit()
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
tryToInit();
|
||||
})
|
||||
}
|
||||
scope.init();
|
||||
})();
|
4523
badicecream/poki.js
Normal file
277
badicecream/preloader/nitromePreloader.js
Normal file
BIN
badicecream/skin/poki-nitrome_border.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
badicecream2/assets/BadIceCream2_sdk.swf
Normal file
BIN
badicecream2/assets/NitromeAPI.pkg
Normal file
BIN
badicecream2/assets/badicecream_splash.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
badicecream2/assets/builtins/avmplus.abc
Normal file
BIN
badicecream2/assets/builtins/builtin.abc
Normal file
BIN
badicecream2/assets/builtins/playerglobal.abcs
Normal file
2753
badicecream2/assets/builtins/playerglobal.json
Normal file
BIN
badicecream2/bad-ice-cream-2.png
Normal file
After Width: | Height: | Size: 95 KiB |
163
badicecream2/index.html
Normal file
@ -0,0 +1,163 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="#382C2A" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
||||
|
||||
<title>Bad Ice Cream 2</title>
|
||||
<script src="/js/all.js"></script>
|
||||
|
||||
<script src="poki.js"></script>
|
||||
<script type="text/javascript" src="./js/loader.js"></script>
|
||||
<script type="text/javascript" src="./js/virtualJoystickSkinMod.js"></script>
|
||||
<script type="text/javascript" src="./preloader/nitromePreloader.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
canvas {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#container {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #9badbe;
|
||||
}
|
||||
|
||||
#splash {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#splash__image {
|
||||
position: absolute;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("assets/badicecream_splash.jpg");
|
||||
visibility: visible;
|
||||
transition: opacity 0.5s;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#progress__root {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#progress__line {
|
||||
width: 0;
|
||||
height: 100%;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="splash__image">
|
||||
<div id="progress__root">
|
||||
<div id="progress__line"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.addEventListener("load", () => {
|
||||
PokiSDK.setDebugTouchOverlayController(true);
|
||||
|
||||
PokiSDK.init()
|
||||
.then(() => {
|
||||
// successfully initialized
|
||||
onPokiInitComplete(false);
|
||||
})
|
||||
.catch(() => {
|
||||
// successfully initialized but the user has adblock
|
||||
onPokiInitComplete(true);
|
||||
});
|
||||
|
||||
let config;
|
||||
|
||||
config = {
|
||||
title: "BadIceCream 2",
|
||||
filename: "BadIceCream2",
|
||||
pokiSDK: true,
|
||||
debugPoki: false,
|
||||
showFPS: false,
|
||||
debug: false,
|
||||
splash: "assets/badicecream_splash.jpg",
|
||||
start: null,
|
||||
width: 550,
|
||||
height: 550,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: "100%",
|
||||
h: "100%",
|
||||
stageScaleMode: null,
|
||||
stageAlign: null,
|
||||
progressParserWeigth: 1,
|
||||
progress: {
|
||||
direction: "lr",
|
||||
back: "#35809e",
|
||||
line: "#070bff",
|
||||
rect: [0.25, 0.65, 0.5, 0.03],
|
||||
},
|
||||
skipFramesOfScene: null,
|
||||
buttonPokiSDKActions: null,
|
||||
retryButtonIDS: null,
|
||||
retryButtonAction: null,
|
||||
actionOnStop: null,
|
||||
actionWhenRetryButtonEncountered: null,
|
||||
binary: [
|
||||
{
|
||||
name: "BadIceCream2",
|
||||
path: "assets/BadIceCream2_sdk.swf",
|
||||
size: 3207867,
|
||||
resourceType: "GAME",
|
||||
},
|
||||
],
|
||||
runtime: "js/BadIceCream.js",
|
||||
};
|
||||
|
||||
PokiSDK.setDebug(config.debugPoki);
|
||||
|
||||
Loader.init(config);
|
||||
|
||||
let onPokiInitComplete = (adBlocked) => {
|
||||
PokiSDK.adBlocked = adBlocked;
|
||||
PokiSDK.gameLoadingStart();
|
||||
|
||||
Loader.runGame(
|
||||
(fill) => {
|
||||
PokiSDK.gameLoadingProgress({
|
||||
percentageDone: fill,
|
||||
kbLoaded: 0,
|
||||
kbTotal: 0,
|
||||
fileNameLoaded: "",
|
||||
filesLoaded: 0,
|
||||
filesTotal: 0,
|
||||
});
|
||||
window.nitromePreloaderSetProgress(fill / 1.0);
|
||||
},
|
||||
(instance) => {
|
||||
PokiSDK.gameLoadingFinished();
|
||||
window.nitromePreloaderSetComplete();
|
||||
}
|
||||
);
|
||||
};
|
||||
window.nitromePreloaderInit("bad-ice-cream-2");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
1
badicecream2/js/BadIceCream.js
Normal file
329
badicecream2/js/loader.js
Normal file
@ -0,0 +1,329 @@
|
||||
var Loader = (function () {
|
||||
function loadBinary(file, progressEvent = f => f) {
|
||||
const req = new XMLHttpRequest();
|
||||
const isScript = file.path.indexOf(".js") > -1;
|
||||
|
||||
req.addEventListener("progress", e => {
|
||||
const total = e.total || file.size;
|
||||
|
||||
if(!total) {
|
||||
progressEvent(1);
|
||||
return;
|
||||
}
|
||||
|
||||
progressEvent(Math.min(1, e.loaded / total) );
|
||||
});
|
||||
|
||||
req.open("GET", file.path, true);
|
||||
req.responseType = isScript ? "text" : "arraybuffer";
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
req.addEventListener("error", rej);
|
||||
req.addEventListener("load", () => {
|
||||
progressEvent(1);
|
||||
|
||||
if (isScript) {
|
||||
// unsafe
|
||||
//eval(req.response);
|
||||
|
||||
const b = new Blob([req.response], { type: "text/javascript" });
|
||||
// use blob
|
||||
loadScript(URL.createObjectURL(b)).then(() => res(undefined));
|
||||
|
||||
return;
|
||||
}
|
||||
res({
|
||||
meta: file.meta || {},
|
||||
name: file.name,
|
||||
path: file.path,
|
||||
resourceType: file.resourceType,
|
||||
data: req.response,
|
||||
type: isScript ? "js" : "swf",
|
||||
});
|
||||
});
|
||||
|
||||
req.send();
|
||||
});
|
||||
}
|
||||
|
||||
function loadScript(file, progress) {
|
||||
const head = document.querySelector("head");
|
||||
const script = document.createElement("script");
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
Object.assign(script, {
|
||||
type: "text/javascript",
|
||||
async: true,
|
||||
src: file.path || file,
|
||||
onload: () => {
|
||||
progress && progress(1);
|
||||
res(script);
|
||||
},
|
||||
onerror: rej,
|
||||
onreadystatechange: s => {
|
||||
if (script.readyState == "complete") { }
|
||||
},
|
||||
});
|
||||
|
||||
head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
function createReporter(callback, childs, weight) {
|
||||
const reporter = {
|
||||
callback: callback,
|
||||
childs: childs ? childs.slice() : undefined,
|
||||
value: 0,
|
||||
weight: weight || 1,
|
||||
|
||||
get report() {
|
||||
return function (v) {
|
||||
if (!this.childs) {
|
||||
this.value = v * this.weight;
|
||||
} else {
|
||||
let summ = 0;
|
||||
let v = 0;
|
||||
|
||||
this.childs.forEach((e) => {
|
||||
summ += e.weight || 1;
|
||||
v += (e.value || 0);
|
||||
});
|
||||
|
||||
this.value = v / summ;
|
||||
}
|
||||
|
||||
this.callback && this.callback(this.value);
|
||||
}.bind(this);
|
||||
},
|
||||
};
|
||||
|
||||
if (childs) {
|
||||
childs.forEach(e => {
|
||||
e.callback = reporter.report;
|
||||
});
|
||||
}
|
||||
|
||||
return reporter;
|
||||
}
|
||||
|
||||
function runLoadingProcess(jsFiles, binaryFiles, progressEvent = f => f, _debugScripts) {
|
||||
const jsCount = jsFiles.length;
|
||||
const binCount = binaryFiles.length;
|
||||
|
||||
const all = jsFiles.concat(binaryFiles);
|
||||
|
||||
const reporters = Array.from({ length: jsCount + binCount }, () => createReporter());
|
||||
createReporter(progressEvent, reporters);
|
||||
|
||||
let pendings;
|
||||
|
||||
if (!_debugScripts) {
|
||||
pendings = all.map((e, i) => loadBinary(e, reporters[i].report));
|
||||
} else {
|
||||
pendings = binaryFiles.map((e, i) => loadBinary(e, reporters[i].report))
|
||||
pendings = pendings.concat(jsFiles.map((e, i) => loadScript(e, reporters[i + binCount].report)))
|
||||
}
|
||||
|
||||
return Promise.all(pendings).then(data => {
|
||||
return data.filter(e => e && e.type === 'swf');
|
||||
});
|
||||
}
|
||||
|
||||
let fillLine = undefined;
|
||||
let __config = undefined;
|
||||
let __splash = undefined;
|
||||
let __pr__root = undefined;
|
||||
let handleResize = undefined;
|
||||
|
||||
window["setStageDimensions"]=function(x, y, w, h){
|
||||
__config.x=x;
|
||||
__config.y=y;
|
||||
__config.w=w;
|
||||
__config.h=h;
|
||||
if(window["AVMPlayerPoki"]){
|
||||
window["AVMPlayerPoki"].setStageDimensions(x, y, w, h);
|
||||
}
|
||||
if(handleResize){
|
||||
handleResize();
|
||||
}
|
||||
}
|
||||
|
||||
function runGame(progressEvent = f => f, completeEvent = f => f) {
|
||||
|
||||
if (!__config) {
|
||||
init();
|
||||
}
|
||||
|
||||
let jss = Array.isArray(__config.runtime) ? jss : [__config.runtime];
|
||||
jss = jss.map(e => ({ path: e.path || e, size: e.size || 0 }));
|
||||
|
||||
const bins = __config.binary;
|
||||
|
||||
const loadReporter = createReporter(null, null, 4);
|
||||
const avmReporter = createReporter((f) => {
|
||||
console.log('AVM Load', f);
|
||||
}, null, __config.progressParserWeigth ? __config.progressParserWeigth : 0.001);
|
||||
|
||||
createReporter(function (fill) {
|
||||
fillLine(fill);
|
||||
// rereport
|
||||
progressEvent(fill);
|
||||
}, [loadReporter, avmReporter])
|
||||
|
||||
const complete = f => {
|
||||
// rereport
|
||||
completeEvent(f);
|
||||
|
||||
if (__config.start) {
|
||||
|
||||
// start image exists.
|
||||
// hide progressbar, show startimage and wait for user-input to start the game
|
||||
|
||||
Object.assign(__pr__root.style, {
|
||||
visibility: "hidden",
|
||||
opacity: 0,
|
||||
});
|
||||
Object.assign(__splash, { backgroundImage: `url(${__config.start})` });
|
||||
let onCLick = (e) => {
|
||||
window.removeEventListener("click", onCLick);
|
||||
Object.assign(__splash.style, {
|
||||
visibility: "hidden",
|
||||
opacity: 0,
|
||||
});
|
||||
if (!f)
|
||||
throw ("PokiPlayer did not send a callback for starting game");
|
||||
f();
|
||||
window.setTimeout(()=>{
|
||||
window.removeEventListener("resize", handleResize);
|
||||
handleResize=null;
|
||||
}, 500)
|
||||
};
|
||||
window.addEventListener("click", onCLick);
|
||||
}
|
||||
else {
|
||||
// no start image.
|
||||
// game will be started automatically
|
||||
Object.assign(__splash.style, {
|
||||
visibility: "hidden",
|
||||
opacity: 0,
|
||||
});
|
||||
// use Timeout, so css transition can complete first
|
||||
window.setTimeout(()=>{
|
||||
window.removeEventListener("resize", handleResize);
|
||||
handleResize=null;
|
||||
}, 500)
|
||||
}
|
||||
};
|
||||
|
||||
runLoadingProcess(jss, bins, loadReporter.report, __config.debug).then(data => {
|
||||
const runner = window["startPokiGame"];
|
||||
if (!runner) {
|
||||
throw "Could not find a 'startPokiGame' method";
|
||||
}
|
||||
|
||||
__config.files = data;
|
||||
|
||||
runner(__config);
|
||||
|
||||
// now poki player is available at window["AVMPlayerPoki"]
|
||||
// can be used to update the stageDimensions:
|
||||
// window["AVMPlayerPoki"].setStageDimensions(x, y, w, h);
|
||||
// values can be
|
||||
// numbers (absolute pixel values)
|
||||
// strings (percentage of window.innerHeight/innerWidth in 0-100)
|
||||
});
|
||||
|
||||
// make functions avilailable on window, so the loaded js-code can access and execute them
|
||||
Object.assign(window, {
|
||||
updatePokiProgressBar: avmReporter.report,
|
||||
pokiGameParseComplete: complete,
|
||||
});
|
||||
}
|
||||
|
||||
function init(config) {
|
||||
if (!config) {
|
||||
throw new Error("Config is required");
|
||||
}
|
||||
|
||||
__config = config;
|
||||
|
||||
const splash = document.querySelector("#splash__image");
|
||||
const pr__root = document.querySelector("#progress__root");
|
||||
const pr__line = document.querySelector("#progress__line");
|
||||
|
||||
__splash = splash;
|
||||
__pr__root = pr__root;
|
||||
|
||||
const pr_conf = config.progress;
|
||||
pr_conf.rect = pr_conf.rect || [0, 0.9, 1, 0.2];
|
||||
|
||||
Object.assign(splash.style, {
|
||||
backgroundImage: `url(${config.splash})`,
|
||||
visibility: "visible",
|
||||
});
|
||||
|
||||
Object.assign(pr__root.style, {
|
||||
background: pr_conf.back,
|
||||
left: `${100 * pr_conf.rect[0]}%`,
|
||||
top: `${100 * pr_conf.rect[1]}%`,
|
||||
width: `${100 * pr_conf.rect[2]}%`,
|
||||
height: `${100 * pr_conf.rect[3]}%`,
|
||||
});
|
||||
|
||||
Object.assign(pr__line.style, {
|
||||
background: pr_conf.line,
|
||||
});
|
||||
|
||||
fillLine = fill => {
|
||||
switch (pr_conf.direction) {
|
||||
case "tb": {
|
||||
Object.assign(pr__line.style, {
|
||||
height: `${fill * 100}%`,
|
||||
width: "100%",
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "lr":
|
||||
default: {
|
||||
Object.assign(pr__line.style, {
|
||||
height: "100%",
|
||||
width: `${fill * 100}%`,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleResize = () => {
|
||||
let x=(typeof config.x==="string")?parseFloat(config.x.replace("%", ""))/100*window.innerWidth:config.x;
|
||||
let y=(typeof config.y==="string")?parseFloat(config.y.replace("%", ""))/100*window.innerHeight:config.y;
|
||||
let w=(typeof config.w==="string")?parseFloat(config.w.replace("%", ""))/100*window.innerWidth:config.w;
|
||||
let h=(typeof config.h==="string")?parseFloat(config.h.replace("%", ""))/100*window.innerHeight:config.h;
|
||||
|
||||
if(!x) x=0;
|
||||
if(!y) y=0;
|
||||
if(!w) w=window.innerWidth;
|
||||
if(!h) h=window.innerHeight;
|
||||
|
||||
const minMax = Math.min(h / config.height, w / config.width);
|
||||
const rw = Math.ceil(config.width * minMax);
|
||||
const rh = Math.ceil(config.height * minMax);
|
||||
const rx = x+(w - rw) / 2;
|
||||
const ry = y+(h - rh) / 2;
|
||||
|
||||
Object.assign(splash.style, {
|
||||
width: `${rw}px`,
|
||||
height: `${rh}px`,
|
||||
left: `${rx}px`,
|
||||
top: `${ry}px`,
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
handleResize();
|
||||
}
|
||||
|
||||
return {
|
||||
init,
|
||||
runGame,
|
||||
};
|
||||
})();
|
347
badicecream2/js/virtualJoystickSkinMod.js
Normal file
@ -0,0 +1,347 @@
|
||||
const isMobile = /Mobi|Android/i.test(navigator.userAgent);
|
||||
if(!isMobile){
|
||||
window.addEventListener('load', ()=>{
|
||||
document.body.style.backgroundImage = 'url(./skin/poki-nitrome_border.png)';
|
||||
document.body.style.backgroundSize = 'cover';
|
||||
document.body.style.backgroundPosition = 'center';
|
||||
});
|
||||
}
|
||||
|
||||
(function (){
|
||||
var scope = {};
|
||||
|
||||
scope.gameCanvas = null;
|
||||
scope.skinnerObject = null;
|
||||
scope.target = null;
|
||||
scope.edgeLeft = null;
|
||||
scope.edgeRight = null;
|
||||
scope.logo = null;
|
||||
scope.home = null;
|
||||
scope.pauseBut = null;
|
||||
scope.pokiLogo = null;
|
||||
scope.frameConfig = {width:480, height:480};
|
||||
scope.portraitOffset = 0;
|
||||
scope.isOnPoki = new URLSearchParams(window.location.search).has('tag');
|
||||
|
||||
scope.getPortraitOffset = function(){
|
||||
const landscape = window.innerWidth > window.innerHeight;
|
||||
const aspect = window.innerWidth/window.innerHeight;
|
||||
const isIpad = (!landscape && aspect >= 0.75) || (landscape && aspect <= 1.34);
|
||||
|
||||
if(landscape){
|
||||
scope.portraitOffset = 0;
|
||||
window["setStageDimensions"](0, 0, "100%", "100%");
|
||||
}else{
|
||||
|
||||
if(isIpad){
|
||||
const frameHeight = window.innerWidth;
|
||||
const gap = (window.innerHeight-frameHeight)/2;
|
||||
scope.portraitOffset = -(gap-gap*(0.5/3));
|
||||
window["setStageDimensions"](0, scope.portraitOffset, "100%", "100%");
|
||||
}else{
|
||||
const frameHeight = window.innerWidth;
|
||||
const gap = (window.innerHeight-frameHeight)/2;
|
||||
scope.portraitOffset = -(gap-gap*(2/3));
|
||||
window["setStageDimensions"](0, scope.portraitOffset, "100%", "100%");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scope.placeSprites = function(){
|
||||
scope.edgeLeft = scope.target.domElement.parentNode.appendChild(scope.createTile(scope.skinnerObject.sprites['edge.png']));
|
||||
scope.edgeRight = scope.target.domElement.parentNode.appendChild(scope.createTile(scope.skinnerObject.sprites['edge.png']));
|
||||
|
||||
scope.logo = scope.target.domElement.parentNode.appendChild(scope.skinnerObject.createImage(scope.skinnerObject.sprites['nitrome_small.png']));
|
||||
scope.logo.style.pointerEvents = 'all';
|
||||
scope.logoPresses = 0;
|
||||
scope.logo.addEventListener('touchstart', ()=>{
|
||||
|
||||
scope.logoPresses++;
|
||||
|
||||
if(scope.logoReleaseTimeout) clearTimeout(scope.logoReleaseTimeout);
|
||||
scope.logoReleaseTimeout = setTimeout(()=>{
|
||||
scope.logoPresses = 0;
|
||||
}, 1000);
|
||||
|
||||
if(scope.logoPresses === 3){
|
||||
const gameboySkin = 'sepia(1) hue-rotate(20deg) brightness(0.65) saturate(0.9)';
|
||||
document.documentElement.style.transition = 'filter 0.5s cubic-bezier(.96,.29,.83,.67) 0s';
|
||||
if(document.documentElement.style.filter === gameboySkin) document.documentElement.style.filter = 'unset';
|
||||
else document.documentElement.style.filter = gameboySkin;
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
if(!scope.isOnPoki){
|
||||
scope.home = scope.target.domElement.parentNode.appendChild(scope.skinnerObject.createImage(scope.skinnerObject.sprites['home.png']));
|
||||
scope.home.style.pointerEvents = 'all';
|
||||
scope.home.style.touchAction = 'none';
|
||||
|
||||
scope.home.ontouchstart = ()=>{
|
||||
scope.home.src = scope.skinnerObject.sprites['home_down.png'];
|
||||
}
|
||||
scope.home.ontouchend = ()=>{
|
||||
scope.home.src = scope.skinnerObject.sprites['home.png'];
|
||||
window.history.back();
|
||||
}
|
||||
}
|
||||
|
||||
scope.pauseBut = document.createElement('div');
|
||||
scope.pauseBut.style.visibility = 'hidden';
|
||||
scope.pauseBut.style.position = 'absolute';
|
||||
scope.target.domElement.parentNode.appendChild(scope.pauseBut);
|
||||
const pauseButtonImage = scope.skinnerObject.createImage(scope.skinnerObject.sprites['pause.png']);
|
||||
pauseButtonImage.style.transform = 'unset';
|
||||
pauseButtonImage.onload = ()=>{
|
||||
scope.pauseBut.style.width = `${pauseButtonImage.width}px`;
|
||||
scope.pauseBut.style.height = `${pauseButtonImage.height}px`;
|
||||
scope.pauseBut.style.visibility = 'visible';
|
||||
}
|
||||
scope.pauseBut.appendChild(pauseButtonImage);
|
||||
scope.pauseBut.style.pointerEvents = 'all';
|
||||
scope.pauseBut.style.touchAction = 'none';
|
||||
scope.pauseBut.ontouchstart = ()=>{
|
||||
scope.target.triggerKeyEvent('keydown', 'P'.charCodeAt(0));
|
||||
setTimeout(()=>{scope.target.triggerKeyEvent('keyup', 'P'.charCodeAt(0))}, 50);
|
||||
const bounds = scope.gameCanvas.getBoundingClientRect();
|
||||
try{
|
||||
if(scope.gameCanvas){
|
||||
let touchEvent;
|
||||
if(scope.isPaused){
|
||||
touchEvent = new Event('touchend');
|
||||
touchEvent.touches = touchEvent.changedTouches = [{clientX: bounds.left+bounds.width/2, clientY: bounds.top+5}];
|
||||
}else{
|
||||
touchEvent = new Event('touchstart');
|
||||
touchEvent.touches = touchEvent.changedTouches = [{clientX: bounds.left+bounds.width-10, clientY: bounds.top+10}];
|
||||
}
|
||||
scope.gameCanvas.dispatchEvent(touchEvent)
|
||||
scope.isPaused = !scope.isPaused;
|
||||
}
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
pauseButtonImage.src = scope.skinnerObject.sprites['pause_down.png'];
|
||||
}
|
||||
scope.pauseBut.ontouchend = ()=>{
|
||||
pauseButtonImage.src = scope.skinnerObject.sprites['pause.png'];
|
||||
}
|
||||
|
||||
scope.pokiLogo = scope.target.domElement.parentNode.appendChild(scope.skinnerObject.createImage(scope.skinnerObject.sprites['poki_large.png']));
|
||||
scope.pokiLogo.style.transform = 'unset';
|
||||
scope.pokiLogo.style.bottom = '6px';
|
||||
scope.pokiLogo.style.right = '6px';
|
||||
}
|
||||
|
||||
scope.resize = function(){
|
||||
const landscape = window.innerWidth > window.innerHeight;
|
||||
|
||||
|
||||
const aspect = window.innerWidth / window.innerHeight;
|
||||
|
||||
const isIpad = (!landscape && aspect >= 0.75) || (landscape && aspect <= 1.34);
|
||||
const edgeSize = 9;
|
||||
scope.getPortraitOffset();
|
||||
const topItemsMargin = 20;
|
||||
|
||||
//have to reset the bounding rect after every repositioning
|
||||
scope.target.virtualJoystick.boundingRect = null;
|
||||
|
||||
|
||||
const preloader = document.querySelector('#nitrome-preloader');
|
||||
|
||||
scope.pokiLogo.src = scope.skinnerObject.sprites['poki_large.png'];
|
||||
|
||||
|
||||
|
||||
if(landscape){
|
||||
const frameWidth = window.innerHeight;
|
||||
const gap = (window.innerWidth-frameWidth)/2;
|
||||
|
||||
scope.edgeLeft.style.left = `${gap}px`;
|
||||
scope.edgeLeft.style.top = `0px`;
|
||||
scope.edgeLeft.style.height = `${window.innerHeight}px`;
|
||||
scope.edgeLeft.style.width = `${edgeSize}px`
|
||||
scope.edgeLeft.style.transform = 'translate(-100%, 0%)';
|
||||
|
||||
scope.edgeRight.style.left = `${gap+frameWidth}px`;
|
||||
scope.edgeRight.style.top = `0px`;
|
||||
scope.edgeRight.style.height = `${window.innerHeight}px`;
|
||||
scope.edgeRight.style.width = `${edgeSize}px`
|
||||
scope.edgeRight.style.transform = 'translate(0%, 0%) rotateZ(180deg)';
|
||||
|
||||
scope.logo.src = scope.skinnerObject.sprites['nitrome_small.png'];
|
||||
|
||||
scope.logo.style.left = `unset`;
|
||||
|
||||
if(!isIpad){
|
||||
scope.logo.style.top = `${topItemsMargin}px`;
|
||||
scope.logo.style.right = `${topItemsMargin*2.3}px`;
|
||||
scope.logo.style.transform = 'translate(-100%, 10%)';
|
||||
}else{
|
||||
scope.logo.style.top = `${topItemsMargin*2}px`;
|
||||
scope.logo.style.right = `${topItemsMargin}px`;
|
||||
scope.logo.style.transform = 'translate(-6%, 100%)';
|
||||
}
|
||||
|
||||
if(scope.home){
|
||||
scope.home.style.top = scope.home.style.left = `${topItemsMargin}px`;
|
||||
scope.home.style.transform = 'unset';
|
||||
}
|
||||
|
||||
scope.pauseBut.style.top = scope.pauseBut.style.right = `${topItemsMargin}px`;
|
||||
scope.pauseBut.style.left = `unset`;
|
||||
scope.pauseBut.style.transform = 'unset';
|
||||
|
||||
scope.skinnerObject.joystickElement.style.left = `${gap/2-edgeSize/2}px`;
|
||||
scope.skinnerObject.joystickElement.style.top = `unset`;
|
||||
scope.skinnerObject.joystickElement.style.bottom = `80px`;
|
||||
|
||||
scope.skinnerObject.buttonsElement.style.left = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.right = `${gap/2-edgeSize/2}px`;
|
||||
scope.skinnerObject.buttonsElement.style.top = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.bottom = `80px`;
|
||||
scope.skinnerObject.buttonsElement.style.paddingLeft = 'unset';
|
||||
|
||||
if(preloader){
|
||||
preloader.style.top = `${window.innerHeight/2}px`;
|
||||
}
|
||||
|
||||
if(isIpad){
|
||||
scope.pokiLogo.src = scope.skinnerObject.sprites['poki_small.png'];
|
||||
}
|
||||
|
||||
}else{
|
||||
const frameHeight = window.innerWidth;
|
||||
const gap = (window.innerHeight-frameHeight)/2;
|
||||
|
||||
scope.edgeLeft.style.left = `${window.innerWidth/2}px`;
|
||||
scope.edgeLeft.style.top = `${gap-edgeSize/2+scope.portraitOffset}px`;
|
||||
scope.edgeLeft.style.width = `${edgeSize}px`
|
||||
scope.edgeLeft.style.height = `${window.innerWidth}px`;
|
||||
scope.edgeLeft.style.transform = 'translate(-50%, -50%) rotateZ(90deg)';
|
||||
|
||||
scope.edgeRight.style.left = `${window.innerWidth/2}px`;
|
||||
scope.edgeRight.style.top = `${gap+frameHeight+edgeSize/2+scope.portraitOffset}px`;
|
||||
scope.edgeRight.style.width = `${edgeSize}px`
|
||||
scope.edgeRight.style.height = `${window.innerWidth}px`;
|
||||
scope.edgeRight.style.transform = 'translate(-50%, -50%) rotateZ(-90deg)';
|
||||
|
||||
scope.logo.src = scope.skinnerObject.sprites['nitrome_full.png'];
|
||||
if(!isIpad){
|
||||
scope.logo.style.bottom = 'unset'
|
||||
scope.logo.style.top = `${-scope.portraitOffset-edgeSize/2}px`;
|
||||
}else{
|
||||
scope.logo.style.bottom = `6px`;
|
||||
scope.logo.style.top = `unset`;
|
||||
}
|
||||
scope.logo.style.right = `unset`;
|
||||
scope.logo.style.left = `${window.innerWidth/2}px`;
|
||||
scope.logo.style.transform = 'translate(-50%, -50%)';
|
||||
|
||||
if(scope.home){
|
||||
if(!isIpad){
|
||||
scope.home.style.bottom = 'unset';
|
||||
scope.home.style.top = `${-scope.portraitOffset-edgeSize/2}px`;
|
||||
scope.home.style.left = `${topItemsMargin}px`;
|
||||
scope.home.style.transform = 'translate(0%, -50%)';
|
||||
}else{
|
||||
scope.home.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
scope.home.style.top = `unset`;
|
||||
scope.home.style.left = `${window.innerWidth/2 - topItemsMargin*1.5}px`;
|
||||
scope.home.style.transform = 'translate(-50%, 50%)';
|
||||
}
|
||||
}
|
||||
|
||||
if(!isIpad){
|
||||
scope.pauseBut.style.bottom = 'unset';
|
||||
scope.pauseBut.style.top = `${-scope.portraitOffset-edgeSize/2}px`;
|
||||
scope.pauseBut.style.right = `${topItemsMargin}px`;
|
||||
scope.pauseBut.style.transform = 'translate(0%, -50%)';
|
||||
}else{
|
||||
scope.pauseBut.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
scope.pauseBut.style.top = `unset`;
|
||||
scope.pauseBut.style.right = `${window.innerWidth/2 - topItemsMargin*1.5}px`;
|
||||
scope.pauseBut.style.transform = 'translate(50%, 50%)';
|
||||
}
|
||||
|
||||
if(!isIpad){
|
||||
scope.skinnerObject.joystickElement.style.left = `30%`;
|
||||
}else{
|
||||
scope.skinnerObject.joystickElement.style.left = `15%`;
|
||||
}
|
||||
scope.skinnerObject.joystickElement.style.top = `unset`;
|
||||
scope.skinnerObject.joystickElement.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
|
||||
if(!isIpad){
|
||||
scope.skinnerObject.buttonsElement.style.right = `26%`;
|
||||
}else{
|
||||
scope.skinnerObject.buttonsElement.style.right = `14%`;
|
||||
}
|
||||
scope.skinnerObject.buttonsElement.style.left = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.top = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
|
||||
if(preloader){
|
||||
preloader.style.top = `${window.innerHeight/2+scope.portraitOffset}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
scope.createTile = function(src){
|
||||
const image = document.createElement('div');
|
||||
image.style.background = `url(${src})`;
|
||||
image.style.position = 'absolute';
|
||||
image.style.transform = 'translate(-50%, -50%)';
|
||||
return image;
|
||||
}
|
||||
scope.init = function(){
|
||||
document.addEventListener('tOCParsed', function(e){
|
||||
const tryToInit = ()=>{
|
||||
try{
|
||||
scope.skinnerObject = e.skinner;
|
||||
scope.target = scope.skinnerObject.target;
|
||||
scope.getPortraitOffset();
|
||||
scope.placeSprites();
|
||||
window.addEventListener('resize', scope.resize);
|
||||
scope.resize();
|
||||
|
||||
if(scope.portraitOffset === 0){
|
||||
// [iOS] Fix initial resizing not going well
|
||||
setTimeout(()=>{
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
},
|
||||
3000)
|
||||
}
|
||||
}catch(e){
|
||||
console.log(e, "FAILED INIT");
|
||||
setTimeout(() => {
|
||||
tryToInit()
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
tryToInit();
|
||||
|
||||
const oldGameplayStart = PokiSDK.gameplayStart;
|
||||
PokiSDK.gameplayStart = ()=>{
|
||||
scope.cancelNextPress = true;
|
||||
oldGameplayStart();
|
||||
}
|
||||
|
||||
const searchCanvasInterval = setInterval(()=>{
|
||||
const canvas = document.querySelector('canvas');
|
||||
if(canvas){
|
||||
scope.gameCanvas = canvas;
|
||||
clearInterval(searchCanvasInterval);
|
||||
scope.gameCanvas.addEventListener('touchstart', ()=>{
|
||||
if (!scope.cancelNextPress && parseFloat(scope.target.domElement.style.opacity) <= scope.target.settings.offOpacity) {
|
||||
scope.target.triggerKeyEvent('keydown', 32);
|
||||
}
|
||||
scope.cancelNextPress = false;
|
||||
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
})
|
||||
}
|
||||
scope.init();
|
||||
})();
|
4523
badicecream2/poki.js
Normal file
277
badicecream2/preloader/nitromePreloader.js
Normal file
BIN
badicecream2/skin/poki-nitrome_border.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
badicecream3/assets/BadIceCream3_sdk.swf
Normal file
BIN
badicecream3/assets/NitromeAPI.pkg
Normal file
BIN
badicecream3/assets/badicecream_splash.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
badicecream3/assets/builtins/avmplus.abc
Normal file
BIN
badicecream3/assets/builtins/builtin.abc
Normal file
BIN
badicecream3/assets/builtins/playerglobal.abcs
Normal file
2753
badicecream3/assets/builtins/playerglobal.json
Normal file
BIN
badicecream3/bad-ice-cream-3.png
Normal file
After Width: | Height: | Size: 148 KiB |
165
badicecream3/index.html
Normal file
@ -0,0 +1,165 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="#382C2A" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
||||
|
||||
<title>Bad Ice Cream 3</title>
|
||||
<script src="/js/all.js"></script>
|
||||
|
||||
<script src="poki.js"></script>
|
||||
<script type="text/javascript" src="./js/loader.js"></script>
|
||||
<script type="text/javascript" src="./js/virtualJoystickSkinMod.js"></script>
|
||||
<script type="text/javascript" src="./preloader/nitromePreloader.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
canvas {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#container {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #9badbe;
|
||||
}
|
||||
|
||||
#splash {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#splash__image {
|
||||
position: absolute;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("assets/badicecream_splash.jpg");
|
||||
visibility: visible;
|
||||
transition: opacity 0.5s;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#progress__root {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#progress__line {
|
||||
width: 0;
|
||||
height: 100%;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="splash__image">
|
||||
<div id="progress__root">
|
||||
<div id="progress__line"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.addEventListener("load", () => {
|
||||
PokiSDK.setDebugTouchOverlayController(true);
|
||||
|
||||
PokiSDK.init()
|
||||
.then(() => {
|
||||
// successfully initialized
|
||||
onPokiInitComplete(false);
|
||||
})
|
||||
.catch(() => {
|
||||
// successfully initialized but the user has adblock
|
||||
onPokiInitComplete(true);
|
||||
});
|
||||
|
||||
let config;
|
||||
|
||||
config = {
|
||||
key: "bic3",
|
||||
title: "BadIceCream 3",
|
||||
filename: "BadIceCream3_sdk",
|
||||
pokiSDK: true,
|
||||
debugPoki: false,
|
||||
showFPS: false,
|
||||
debug: false,
|
||||
splash: "assets/badicecream_splash.jpg",
|
||||
start: null,
|
||||
width: 550,
|
||||
height: 550,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: "100%",
|
||||
h: "100%",
|
||||
stageScaleMode: null,
|
||||
stageAlign: null,
|
||||
progressParserWeigth: 1,
|
||||
progress: {
|
||||
direction: "lr",
|
||||
back: "#35809e",
|
||||
line: "#070bff",
|
||||
rect: [0.25, 0.65, 0.5, 0.03],
|
||||
},
|
||||
box2dVersion: "none",
|
||||
skipFramesOfScene: null,
|
||||
buttonPokiSDKActions: null,
|
||||
retryButtonIDS: null,
|
||||
retryButtonAction: null,
|
||||
actionOnStop: null,
|
||||
actionWhenRetryButtonEncountered: null,
|
||||
binary: [
|
||||
{
|
||||
name: "BadIceCream3_sdk",
|
||||
path: "assets/BadIceCream3_sdk.swf",
|
||||
size: 3943834,
|
||||
resourceType: "GAME",
|
||||
},
|
||||
],
|
||||
runtime: "js/BadIceCream.js",
|
||||
};
|
||||
|
||||
PokiSDK.setDebug(config.debugPoki);
|
||||
|
||||
Loader.init(config);
|
||||
|
||||
let onPokiInitComplete = (adBlocked) => {
|
||||
PokiSDK.adBlocked = adBlocked;
|
||||
PokiSDK.gameLoadingStart();
|
||||
|
||||
Loader.runGame(
|
||||
(fill) => {
|
||||
PokiSDK.gameLoadingProgress({
|
||||
percentageDone: fill,
|
||||
kbLoaded: 0,
|
||||
kbTotal: 0,
|
||||
fileNameLoaded: "",
|
||||
filesLoaded: 0,
|
||||
filesTotal: 0,
|
||||
});
|
||||
window.nitromePreloaderSetProgress(fill / 1.0);
|
||||
},
|
||||
(instance) => {
|
||||
PokiSDK.gameLoadingFinished();
|
||||
window.nitromePreloaderSetComplete();
|
||||
}
|
||||
);
|
||||
};
|
||||
window.nitromePreloaderInit("bad-ice-cream-3");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
1
badicecream3/js/BadIceCream.js
Normal file
328
badicecream3/js/loader.js
Normal file
@ -0,0 +1,328 @@
|
||||
var Loader = (function () {
|
||||
function loadBinary(file, progressEvent = f => f) {
|
||||
const req = new XMLHttpRequest();
|
||||
const isScript = file.path.indexOf(".js") > -1;
|
||||
|
||||
req.addEventListener("progress", e => {
|
||||
const total = e.total || file.size;
|
||||
|
||||
if(!total) {
|
||||
progressEvent(1);
|
||||
return;
|
||||
}
|
||||
|
||||
progressEvent(Math.min(1, e.loaded / total) );
|
||||
});
|
||||
|
||||
req.open("GET", file.path, true);
|
||||
req.responseType = isScript ? "text" : "arraybuffer";
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
req.addEventListener("error", rej);
|
||||
req.addEventListener("load", () => {
|
||||
progressEvent(1);
|
||||
|
||||
if (isScript) {
|
||||
// unsafe
|
||||
//eval(req.response);
|
||||
const b = new Blob([req.response], { type: "text/javascript" });
|
||||
// use blob
|
||||
loadScript(URL.createObjectURL(b)).then(() => res(undefined));
|
||||
|
||||
return;
|
||||
}
|
||||
res({
|
||||
meta: file.meta || {},
|
||||
name: file.name,
|
||||
path: file.path,
|
||||
resourceType: file.resourceType,
|
||||
data: req.response,
|
||||
type: isScript ? "js" : "swf",
|
||||
});
|
||||
});
|
||||
|
||||
req.send();
|
||||
});
|
||||
}
|
||||
|
||||
function loadScript(file, progress) {
|
||||
const head = document.querySelector("head");
|
||||
const script = document.createElement("script");
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
Object.assign(script, {
|
||||
type: "text/javascript",
|
||||
async: true,
|
||||
src: file.path || file,
|
||||
onload: () => {
|
||||
progress && progress(1);
|
||||
res(script);
|
||||
},
|
||||
onerror: rej,
|
||||
onreadystatechange: s => {
|
||||
if (script.readyState == "complete") { }
|
||||
},
|
||||
});
|
||||
|
||||
head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
function createReporter(callback, childs, weight) {
|
||||
const reporter = {
|
||||
callback: callback,
|
||||
childs: childs ? childs.slice() : undefined,
|
||||
value: 0,
|
||||
weight: weight || 1,
|
||||
|
||||
get report() {
|
||||
return function (v) {
|
||||
if (!this.childs) {
|
||||
this.value = v * this.weight;
|
||||
} else {
|
||||
let summ = 0;
|
||||
let v = 0;
|
||||
|
||||
this.childs.forEach((e) => {
|
||||
summ += e.weight || 1;
|
||||
v += (e.value || 0);
|
||||
});
|
||||
|
||||
this.value = v / summ;
|
||||
}
|
||||
|
||||
this.callback && this.callback(this.value);
|
||||
}.bind(this);
|
||||
},
|
||||
};
|
||||
|
||||
if (childs) {
|
||||
childs.forEach(e => {
|
||||
e.callback = reporter.report;
|
||||
});
|
||||
}
|
||||
|
||||
return reporter;
|
||||
}
|
||||
|
||||
function runLoadingProcess(jsFiles, binaryFiles, progressEvent = f => f, _debugScripts) {
|
||||
const jsCount = jsFiles.length;
|
||||
const binCount = binaryFiles.length;
|
||||
|
||||
const all = jsFiles.concat(binaryFiles);
|
||||
|
||||
const reporters = Array.from({ length: jsCount + binCount }, () => createReporter());
|
||||
createReporter(progressEvent, reporters);
|
||||
|
||||
let pendings;
|
||||
|
||||
if (!_debugScripts) {
|
||||
pendings = all.map((e, i) => loadBinary(e, reporters[i].report));
|
||||
} else {
|
||||
pendings = binaryFiles.map((e, i) => loadBinary(e, reporters[i].report))
|
||||
pendings = pendings.concat(jsFiles.map((e, i) => loadScript(e, reporters[i + binCount].report)))
|
||||
}
|
||||
|
||||
return Promise.all(pendings).then(data => {
|
||||
return data.filter(e => e && e.type === 'swf');
|
||||
});
|
||||
}
|
||||
|
||||
let fillLine = undefined;
|
||||
let __config = undefined;
|
||||
let __splash = undefined;
|
||||
let __pr__root = undefined;
|
||||
let handleResize = undefined;
|
||||
|
||||
window["setStageDimensions"]=function(x, y, w, h){
|
||||
__config.x=x;
|
||||
__config.y=y;
|
||||
__config.w=w;
|
||||
__config.h=h;
|
||||
if(window["AVMPlayerPoki"]){
|
||||
window["AVMPlayerPoki"].setStageDimensions(x, y, w, h);
|
||||
}
|
||||
if(handleResize){
|
||||
handleResize();
|
||||
}
|
||||
}
|
||||
|
||||
function runGame(progressEvent = f => f, completeEvent = f => f) {
|
||||
|
||||
if (!__config) {
|
||||
init();
|
||||
}
|
||||
|
||||
let jss = Array.isArray(__config.runtime) ? jss : [__config.runtime];
|
||||
jss = jss.map(e => ({ path: e.path || e, size: e.size || 0 }));
|
||||
|
||||
const bins = __config.binary;
|
||||
|
||||
const loadReporter = createReporter(null, null, 4);
|
||||
const avmReporter = createReporter((f) => {
|
||||
console.log('AVM Load', f);
|
||||
}, null, __config.progressParserWeigth ? __config.progressParserWeigth : 0.001);
|
||||
|
||||
createReporter(function (fill) {
|
||||
fillLine(fill);
|
||||
// rereport
|
||||
progressEvent(fill);
|
||||
}, [loadReporter, avmReporter])
|
||||
|
||||
const complete = f => {
|
||||
// rereport
|
||||
completeEvent(f);
|
||||
|
||||
if (__config.start) {
|
||||
|
||||
// start image exists.
|
||||
// hide progressbar, show startimage and wait for user-input to start the game
|
||||
|
||||
Object.assign(__pr__root.style, {
|
||||
visibility: "hidden",
|
||||
opacity: 0,
|
||||
});
|
||||
Object.assign(__splash, { backgroundImage: `url(${__config.start})` });
|
||||
let onCLick = (e) => {
|
||||
window.removeEventListener("click", onCLick);
|
||||
Object.assign(__splash.style, {
|
||||
visibility: "hidden",
|
||||
opacity: 0,
|
||||
});
|
||||
if (!f)
|
||||
throw ("PokiPlayer did not send a callback for starting game");
|
||||
f();
|
||||
window.setTimeout(()=>{
|
||||
window.removeEventListener("resize", handleResize);
|
||||
handleResize=null;
|
||||
}, 500)
|
||||
};
|
||||
window.addEventListener("click", onCLick);
|
||||
}
|
||||
else {
|
||||
// no start image.
|
||||
// game will be started automatically
|
||||
Object.assign(__splash.style, {
|
||||
visibility: "hidden",
|
||||
opacity: 0,
|
||||
});
|
||||
// use Timeout, so css transition can complete first
|
||||
window.setTimeout(()=>{
|
||||
window.removeEventListener("resize", handleResize);
|
||||
handleResize=null;
|
||||
}, 500)
|
||||
}
|
||||
};
|
||||
|
||||
runLoadingProcess(jss, bins, loadReporter.report, __config.debug).then(data => {
|
||||
const runner = window["startPokiGame"];
|
||||
if (!runner) {
|
||||
throw "Could not find a 'startPokiGame' method";
|
||||
}
|
||||
|
||||
__config.files = data;
|
||||
|
||||
runner(__config);
|
||||
|
||||
// now poki player is available at window["AVMPlayerPoki"]
|
||||
// can be used to update the stageDimensions:
|
||||
// window["AVMPlayerPoki"].setStageDimensions(x, y, w, h);
|
||||
// values can be
|
||||
// numbers (absolute pixel values)
|
||||
// strings (percentage of window.innerHeight/innerWidth in 0-100)
|
||||
});
|
||||
|
||||
// make functions avilailable on window, so the loaded js-code can access and execute them
|
||||
Object.assign(window, {
|
||||
updatePokiProgressBar: avmReporter.report,
|
||||
pokiGameParseComplete: complete,
|
||||
});
|
||||
}
|
||||
|
||||
function init(config) {
|
||||
if (!config) {
|
||||
throw new Error("Config is required");
|
||||
}
|
||||
|
||||
__config = config;
|
||||
|
||||
const splash = document.querySelector("#splash__image");
|
||||
const pr__root = document.querySelector("#progress__root");
|
||||
const pr__line = document.querySelector("#progress__line");
|
||||
|
||||
__splash = splash;
|
||||
__pr__root = pr__root;
|
||||
|
||||
const pr_conf = config.progress;
|
||||
pr_conf.rect = pr_conf.rect || [0, 0.9, 1, 0.2];
|
||||
|
||||
Object.assign(splash.style, {
|
||||
backgroundImage: `url(${config.splash})`,
|
||||
visibility: "visible",
|
||||
});
|
||||
|
||||
Object.assign(pr__root.style, {
|
||||
background: pr_conf.back,
|
||||
left: `${100 * pr_conf.rect[0]}%`,
|
||||
top: `${100 * pr_conf.rect[1]}%`,
|
||||
width: `${100 * pr_conf.rect[2]}%`,
|
||||
height: `${100 * pr_conf.rect[3]}%`,
|
||||
});
|
||||
|
||||
Object.assign(pr__line.style, {
|
||||
background: pr_conf.line,
|
||||
});
|
||||
|
||||
fillLine = fill => {
|
||||
switch (pr_conf.direction) {
|
||||
case "tb": {
|
||||
Object.assign(pr__line.style, {
|
||||
height: `${fill * 100}%`,
|
||||
width: "100%",
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "lr":
|
||||
default: {
|
||||
Object.assign(pr__line.style, {
|
||||
height: "100%",
|
||||
width: `${fill * 100}%`,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleResize = () => {
|
||||
let x=(typeof config.x==="string")?parseFloat(config.x.replace("%", ""))/100*window.innerWidth:config.x;
|
||||
let y=(typeof config.y==="string")?parseFloat(config.y.replace("%", ""))/100*window.innerHeight:config.y;
|
||||
let w=(typeof config.w==="string")?parseFloat(config.w.replace("%", ""))/100*window.innerWidth:config.w;
|
||||
let h=(typeof config.h==="string")?parseFloat(config.h.replace("%", ""))/100*window.innerHeight:config.h;
|
||||
|
||||
if(!x) x=0;
|
||||
if(!y) y=0;
|
||||
if(!w) w=window.innerWidth;
|
||||
if(!h) h=window.innerHeight;
|
||||
|
||||
const minMax = Math.min(h / config.height, w / config.width);
|
||||
const rw = Math.ceil(config.width * minMax);
|
||||
const rh = Math.ceil(config.height * minMax);
|
||||
const rx = x+(w - rw) / 2;
|
||||
const ry = y+(h - rh) / 2;
|
||||
|
||||
Object.assign(splash.style, {
|
||||
width: `${rw}px`,
|
||||
height: `${rh}px`,
|
||||
left: `${rx}px`,
|
||||
top: `${ry}px`,
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
handleResize();
|
||||
}
|
||||
|
||||
return {
|
||||
init,
|
||||
runGame,
|
||||
};
|
||||
})();
|
347
badicecream3/js/virtualJoystickSkinMod.js
Normal file
@ -0,0 +1,347 @@
|
||||
const isMobile = /Mobi|Android/i.test(navigator.userAgent);
|
||||
if(!isMobile){
|
||||
window.addEventListener('load', ()=>{
|
||||
document.body.style.backgroundImage = 'url(./skin/poki-nitrome_border.png)';
|
||||
document.body.style.backgroundSize = 'cover';
|
||||
document.body.style.backgroundPosition = 'center';
|
||||
});
|
||||
}
|
||||
|
||||
(function (){
|
||||
var scope = {};
|
||||
|
||||
scope.gameCanvas = null;
|
||||
scope.skinnerObject = null;
|
||||
scope.target = null;
|
||||
scope.edgeLeft = null;
|
||||
scope.edgeRight = null;
|
||||
scope.logo = null;
|
||||
scope.home = null;
|
||||
scope.pauseBut = null;
|
||||
scope.pokiLogo = null;
|
||||
scope.frameConfig = {width:480, height:480};
|
||||
scope.portraitOffset = 0;
|
||||
scope.isOnPoki = new URLSearchParams(window.location.search).has('tag');
|
||||
|
||||
scope.getPortraitOffset = function(){
|
||||
const landscape = window.innerWidth > window.innerHeight;
|
||||
const aspect = window.innerWidth/window.innerHeight;
|
||||
const isIpad = (!landscape && aspect >= 0.75) || (landscape && aspect <= 1.34);
|
||||
|
||||
if(landscape){
|
||||
scope.portraitOffset = 0;
|
||||
window["setStageDimensions"](0, 0, "100%", "100%");
|
||||
}else{
|
||||
|
||||
if(isIpad){
|
||||
const frameHeight = window.innerWidth;
|
||||
const gap = (window.innerHeight-frameHeight)/2;
|
||||
scope.portraitOffset = -(gap-gap*(0.5/3));
|
||||
window["setStageDimensions"](0, scope.portraitOffset, "100%", "100%");
|
||||
}else{
|
||||
const frameHeight = window.innerWidth;
|
||||
const gap = (window.innerHeight-frameHeight)/2;
|
||||
scope.portraitOffset = -(gap-gap*(2/3));
|
||||
window["setStageDimensions"](0, scope.portraitOffset, "100%", "100%");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scope.placeSprites = function(){
|
||||
scope.edgeLeft = scope.target.domElement.parentNode.appendChild(scope.createTile(scope.skinnerObject.sprites['edge.png']));
|
||||
scope.edgeRight = scope.target.domElement.parentNode.appendChild(scope.createTile(scope.skinnerObject.sprites['edge.png']));
|
||||
|
||||
scope.logo = scope.target.domElement.parentNode.appendChild(scope.skinnerObject.createImage(scope.skinnerObject.sprites['nitrome_small.png']));
|
||||
scope.logo.style.pointerEvents = 'all';
|
||||
scope.logoPresses = 0;
|
||||
scope.logo.addEventListener('touchstart', ()=>{
|
||||
|
||||
scope.logoPresses++;
|
||||
|
||||
if(scope.logoReleaseTimeout) clearTimeout(scope.logoReleaseTimeout);
|
||||
scope.logoReleaseTimeout = setTimeout(()=>{
|
||||
scope.logoPresses = 0;
|
||||
}, 1000);
|
||||
|
||||
if(scope.logoPresses === 3){
|
||||
const gameboySkin = 'sepia(1) hue-rotate(20deg) brightness(0.65) saturate(0.9)';
|
||||
document.documentElement.style.transition = 'filter 0.5s cubic-bezier(.96,.29,.83,.67) 0s';
|
||||
if(document.documentElement.style.filter === gameboySkin) document.documentElement.style.filter = 'unset';
|
||||
else document.documentElement.style.filter = gameboySkin;
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
if(!scope.isOnPoki){
|
||||
scope.home = scope.target.domElement.parentNode.appendChild(scope.skinnerObject.createImage(scope.skinnerObject.sprites['home.png']));
|
||||
scope.home.style.pointerEvents = 'all';
|
||||
scope.home.style.touchAction = 'none';
|
||||
|
||||
scope.home.ontouchstart = ()=>{
|
||||
scope.home.src = scope.skinnerObject.sprites['home_down.png'];
|
||||
}
|
||||
scope.home.ontouchend = ()=>{
|
||||
scope.home.src = scope.skinnerObject.sprites['home.png'];
|
||||
window.history.back();
|
||||
}
|
||||
}
|
||||
|
||||
scope.pauseBut = document.createElement('div');
|
||||
scope.pauseBut.style.visibility = 'hidden';
|
||||
scope.pauseBut.style.position = 'absolute';
|
||||
scope.target.domElement.parentNode.appendChild(scope.pauseBut);
|
||||
const pauseButtonImage = scope.skinnerObject.createImage(scope.skinnerObject.sprites['pause.png']);
|
||||
pauseButtonImage.style.transform = 'unset';
|
||||
pauseButtonImage.onload = ()=>{
|
||||
scope.pauseBut.style.width = `${pauseButtonImage.width}px`;
|
||||
scope.pauseBut.style.height = `${pauseButtonImage.height}px`;
|
||||
scope.pauseBut.style.visibility = 'visible';
|
||||
}
|
||||
scope.pauseBut.appendChild(pauseButtonImage);
|
||||
scope.pauseBut.style.pointerEvents = 'all';
|
||||
scope.pauseBut.style.touchAction = 'none';
|
||||
scope.pauseBut.ontouchstart = ()=>{
|
||||
scope.target.triggerKeyEvent('keydown', 'P'.charCodeAt(0));
|
||||
setTimeout(()=>{scope.target.triggerKeyEvent('keyup', 'P'.charCodeAt(0))}, 50);
|
||||
try{
|
||||
if(scope.gameCanvas){
|
||||
const bounds = scope.gameCanvas.getBoundingClientRect();
|
||||
let touchEvent;
|
||||
if(scope.isPaused){
|
||||
touchEvent = new Event('touchend');
|
||||
touchEvent.touches = touchEvent.changedTouches = [{clientX: bounds.left+bounds.width/2, clientY: bounds.top+5}];
|
||||
}else{
|
||||
touchEvent = new Event('touchstart');
|
||||
touchEvent.touches = touchEvent.changedTouches = [{clientX: bounds.left+bounds.width-10, clientY: bounds.top+10}];
|
||||
}
|
||||
scope.gameCanvas.dispatchEvent(touchEvent)
|
||||
scope.isPaused = !scope.isPaused;
|
||||
}
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
pauseButtonImage.src = scope.skinnerObject.sprites['pause_down.png'];
|
||||
}
|
||||
scope.pauseBut.ontouchend = ()=>{
|
||||
pauseButtonImage.src = scope.skinnerObject.sprites['pause.png'];
|
||||
}
|
||||
|
||||
scope.pokiLogo = scope.target.domElement.parentNode.appendChild(scope.skinnerObject.createImage(scope.skinnerObject.sprites['poki_large.png']));
|
||||
scope.pokiLogo.style.transform = 'unset';
|
||||
scope.pokiLogo.style.bottom = '6px';
|
||||
scope.pokiLogo.style.right = '6px';
|
||||
}
|
||||
|
||||
scope.resize = function(){
|
||||
const landscape = window.innerWidth > window.innerHeight;
|
||||
|
||||
|
||||
const aspect = window.innerWidth / window.innerHeight;
|
||||
|
||||
const isIpad = (!landscape && aspect >= 0.75) || (landscape && aspect <= 1.34);
|
||||
const edgeSize = 9;
|
||||
scope.getPortraitOffset();
|
||||
const topItemsMargin = 20;
|
||||
|
||||
//have to reset the bounding rect after every repositioning
|
||||
scope.target.virtualJoystick.boundingRect = null;
|
||||
|
||||
|
||||
const preloader = document.querySelector('#nitrome-preloader');
|
||||
|
||||
scope.pokiLogo.src = scope.skinnerObject.sprites['poki_large.png'];
|
||||
|
||||
|
||||
|
||||
if(landscape){
|
||||
const frameWidth = window.innerHeight;
|
||||
const gap = (window.innerWidth-frameWidth)/2;
|
||||
|
||||
scope.edgeLeft.style.left = `${gap}px`;
|
||||
scope.edgeLeft.style.top = `0px`;
|
||||
scope.edgeLeft.style.height = `${window.innerHeight}px`;
|
||||
scope.edgeLeft.style.width = `${edgeSize}px`
|
||||
scope.edgeLeft.style.transform = 'translate(-100%, 0%)';
|
||||
|
||||
scope.edgeRight.style.left = `${gap+frameWidth}px`;
|
||||
scope.edgeRight.style.top = `0px`;
|
||||
scope.edgeRight.style.height = `${window.innerHeight}px`;
|
||||
scope.edgeRight.style.width = `${edgeSize}px`
|
||||
scope.edgeRight.style.transform = 'translate(0%, 0%) rotateZ(180deg)';
|
||||
|
||||
scope.logo.src = scope.skinnerObject.sprites['nitrome_small.png'];
|
||||
|
||||
scope.logo.style.left = `unset`;
|
||||
|
||||
if(!isIpad){
|
||||
scope.logo.style.top = `${topItemsMargin}px`;
|
||||
scope.logo.style.right = `${topItemsMargin*2.3}px`;
|
||||
scope.logo.style.transform = 'translate(-100%, 10%)';
|
||||
}else{
|
||||
scope.logo.style.top = `${topItemsMargin*2}px`;
|
||||
scope.logo.style.right = `${topItemsMargin}px`;
|
||||
scope.logo.style.transform = 'translate(-6%, 100%)';
|
||||
}
|
||||
|
||||
if(scope.home){
|
||||
scope.home.style.top = scope.home.style.left = `${topItemsMargin}px`;
|
||||
scope.home.style.transform = 'unset';
|
||||
}
|
||||
|
||||
scope.pauseBut.style.top = scope.pauseBut.style.right = `${topItemsMargin}px`;
|
||||
scope.pauseBut.style.left = `unset`;
|
||||
scope.pauseBut.style.transform = 'unset';
|
||||
|
||||
scope.skinnerObject.joystickElement.style.left = `${gap/2-edgeSize/2}px`;
|
||||
scope.skinnerObject.joystickElement.style.top = `unset`;
|
||||
scope.skinnerObject.joystickElement.style.bottom = `80px`;
|
||||
|
||||
scope.skinnerObject.buttonsElement.style.left = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.right = `${gap/2-edgeSize/2}px`;
|
||||
scope.skinnerObject.buttonsElement.style.top = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.bottom = `80px`;
|
||||
scope.skinnerObject.buttonsElement.style.paddingLeft = 'unset';
|
||||
|
||||
if(preloader){
|
||||
preloader.style.top = `${window.innerHeight/2}px`;
|
||||
}
|
||||
|
||||
if(isIpad){
|
||||
scope.pokiLogo.src = scope.skinnerObject.sprites['poki_small.png'];
|
||||
}
|
||||
|
||||
}else{
|
||||
const frameHeight = window.innerWidth;
|
||||
const gap = (window.innerHeight-frameHeight)/2;
|
||||
|
||||
scope.edgeLeft.style.left = `${window.innerWidth/2}px`;
|
||||
scope.edgeLeft.style.top = `${gap-edgeSize/2+scope.portraitOffset}px`;
|
||||
scope.edgeLeft.style.width = `${edgeSize}px`
|
||||
scope.edgeLeft.style.height = `${window.innerWidth}px`;
|
||||
scope.edgeLeft.style.transform = 'translate(-50%, -50%) rotateZ(90deg)';
|
||||
|
||||
scope.edgeRight.style.left = `${window.innerWidth/2}px`;
|
||||
scope.edgeRight.style.top = `${gap+frameHeight+edgeSize/2+scope.portraitOffset}px`;
|
||||
scope.edgeRight.style.width = `${edgeSize}px`
|
||||
scope.edgeRight.style.height = `${window.innerWidth}px`;
|
||||
scope.edgeRight.style.transform = 'translate(-50%, -50%) rotateZ(-90deg)';
|
||||
|
||||
scope.logo.src = scope.skinnerObject.sprites['nitrome_full.png'];
|
||||
if(!isIpad){
|
||||
scope.logo.style.bottom = 'unset'
|
||||
scope.logo.style.top = `${-scope.portraitOffset-edgeSize/2}px`;
|
||||
}else{
|
||||
scope.logo.style.bottom = `6px`;
|
||||
scope.logo.style.top = `unset`;
|
||||
}
|
||||
scope.logo.style.right = `unset`;
|
||||
scope.logo.style.left = `${window.innerWidth/2}px`;
|
||||
scope.logo.style.transform = 'translate(-50%, -50%)';
|
||||
|
||||
if(scope.home){
|
||||
if(!isIpad){
|
||||
scope.home.style.bottom = 'unset';
|
||||
scope.home.style.top = `${-scope.portraitOffset-edgeSize/2}px`;
|
||||
scope.home.style.left = `${topItemsMargin}px`;
|
||||
scope.home.style.transform = 'translate(0%, -50%)';
|
||||
}else{
|
||||
scope.home.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
scope.home.style.top = `unset`;
|
||||
scope.home.style.left = `${window.innerWidth/2 - topItemsMargin*1.5}px`;
|
||||
scope.home.style.transform = 'translate(-50%, 50%)';
|
||||
}
|
||||
}
|
||||
|
||||
if(!isIpad){
|
||||
scope.pauseBut.style.bottom = 'unset';
|
||||
scope.pauseBut.style.top = `${-scope.portraitOffset-edgeSize/2}px`;
|
||||
scope.pauseBut.style.right = `${topItemsMargin}px`;
|
||||
scope.pauseBut.style.transform = 'translate(0%, -50%)';
|
||||
}else{
|
||||
scope.pauseBut.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
scope.pauseBut.style.top = `unset`;
|
||||
scope.pauseBut.style.right = `${window.innerWidth/2 - topItemsMargin*1.5}px`;
|
||||
scope.pauseBut.style.transform = 'translate(50%, 50%)';
|
||||
}
|
||||
|
||||
if(!isIpad){
|
||||
scope.skinnerObject.joystickElement.style.left = `30%`;
|
||||
}else{
|
||||
scope.skinnerObject.joystickElement.style.left = `15%`;
|
||||
}
|
||||
scope.skinnerObject.joystickElement.style.top = `unset`;
|
||||
scope.skinnerObject.joystickElement.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
|
||||
if(!isIpad){
|
||||
scope.skinnerObject.buttonsElement.style.right = `26%`;
|
||||
}else{
|
||||
scope.skinnerObject.buttonsElement.style.right = `14%`;
|
||||
}
|
||||
scope.skinnerObject.buttonsElement.style.left = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.top = `unset`;
|
||||
scope.skinnerObject.buttonsElement.style.bottom = `${gap/2-scope.portraitOffset/2}px`;
|
||||
|
||||
if(preloader){
|
||||
preloader.style.top = `${window.innerHeight/2+scope.portraitOffset}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
scope.createTile = function(src){
|
||||
const image = document.createElement('div');
|
||||
image.style.background = `url(${src})`;
|
||||
image.style.position = 'absolute';
|
||||
image.style.transform = 'translate(-50%, -50%)';
|
||||
return image;
|
||||
}
|
||||
scope.init = function(){
|
||||
document.addEventListener('tOCParsed', function(e){
|
||||
const tryToInit = ()=>{
|
||||
try{
|
||||
scope.skinnerObject = e.skinner;
|
||||
scope.target = scope.skinnerObject.target;
|
||||
scope.getPortraitOffset();
|
||||
scope.placeSprites();
|
||||
window.addEventListener('resize', scope.resize);
|
||||
scope.resize();
|
||||
|
||||
if(scope.portraitOffset === 0){
|
||||
// [iOS] Fix initial resizing not going well
|
||||
setTimeout(()=>{
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
},
|
||||
3000)
|
||||
}
|
||||
}catch(e){
|
||||
console.log(e, "FAILED INIT");
|
||||
setTimeout(() => {
|
||||
tryToInit()
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
tryToInit();
|
||||
|
||||
const oldGameplayStart = PokiSDK.gameplayStart;
|
||||
PokiSDK.gameplayStart = ()=>{
|
||||
scope.cancelNextPress = true;
|
||||
oldGameplayStart();
|
||||
}
|
||||
|
||||
const searchCanvasInterval = setInterval(()=>{
|
||||
const canvas = document.querySelector('canvas');
|
||||
if(canvas){
|
||||
scope.gameCanvas = canvas;
|
||||
clearInterval(searchCanvasInterval);
|
||||
scope.gameCanvas.addEventListener('touchstart', ()=>{
|
||||
if (!scope.cancelNextPress && parseFloat(scope.target.domElement.style.opacity) <= scope.target.settings.offOpacity) {
|
||||
scope.target.triggerKeyEvent('keydown', 32);
|
||||
}
|
||||
scope.cancelNextPress = false;
|
||||
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
})
|
||||
}
|
||||
scope.init();
|
||||
})();
|
4523
badicecream3/poki.js
Normal file
277
badicecream3/preloader/nitromePreloader.js
Normal file
BIN
badicecream3/skin/poki-nitrome_border.png
Normal file
After Width: | Height: | Size: 24 KiB |
203
ballisticchickens/code/achieve.js
Normal file
@ -0,0 +1,203 @@
|
||||
scene('achievements', () => {
|
||||
const Z = {
|
||||
bg: 0,
|
||||
main: 100,
|
||||
top: 200,
|
||||
black: 300,
|
||||
};
|
||||
|
||||
var mainScroll = 0;
|
||||
|
||||
const black = add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
z(Z.black),
|
||||
opacity(1),
|
||||
color(BLACK),
|
||||
fixed(),
|
||||
]);
|
||||
|
||||
for (let f = 0; f < 20; f++) {
|
||||
setTimeout(() => {
|
||||
black.opacity -= 0.05;
|
||||
}, f*15);
|
||||
};
|
||||
|
||||
let fadingOut = false;
|
||||
function fadeOut() {
|
||||
if (!fadingOut) {
|
||||
fadingOut = true;
|
||||
for (let f = 0; f < 20; f++) {
|
||||
setTimeout(() => {
|
||||
black.opacity += 0.05;
|
||||
}, f * FADE_TIME / 15);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
for (let j = 0; j < 2; j++) {
|
||||
for (let i = 0; i < [1,6][j]; i++) {
|
||||
let border = SCALE*0.01;
|
||||
let xOff = Math.sin( (Math.PI * i) /2 ) *border;
|
||||
let yOff = Math.cos( (Math.PI * i) /2 ) *border;
|
||||
if (i == 0) { xOff = 0; yOff = 0; };
|
||||
|
||||
add([
|
||||
text('ACHIEVEMENTS', {
|
||||
size: SCALE*0.87,
|
||||
align: 'center',
|
||||
font: 'burned',
|
||||
letterSpacing: SCALE*0.04,
|
||||
}),
|
||||
pos(width()/2 +xOff, SCALE*0.37 +yOff),
|
||||
origin('top'),
|
||||
z(Z.top +1),
|
||||
color(BLACK),
|
||||
rotate(-1.5),
|
||||
]);
|
||||
};
|
||||
};
|
||||
|
||||
add([
|
||||
rect(width(), SCALE*1.6),
|
||||
pos(0,0),
|
||||
color(rgb(240,240,240)),
|
||||
z(Z.top),
|
||||
]);
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
add([
|
||||
rect(width(), SCALE*0.1),
|
||||
pos(0, SCALE*(1.6 + (i*0.1))),
|
||||
color(BLACK),
|
||||
opacity((2-i)*0.1),
|
||||
z(Z.top),
|
||||
]);
|
||||
};
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
add([
|
||||
rect(width(), SCALE/15),
|
||||
pos(0, SCALE*(0.7*(i+1) -0.3)),
|
||||
color(rgb(140,170,245)),
|
||||
z(Z.top),
|
||||
])
|
||||
};
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
for (let j = 0; j < 2; j++) {
|
||||
add([
|
||||
sprite('cork'),
|
||||
pos(center().add(0, j*SCALE*10)),
|
||||
scale(TILE*5),
|
||||
origin(['topleft', 'botleft', 'topright', 'botright'][i]),
|
||||
z(Z.bg),
|
||||
"scrollable",
|
||||
{
|
||||
startY: center().y + j*SCALE*10,
|
||||
}
|
||||
]);
|
||||
};
|
||||
};
|
||||
|
||||
add([
|
||||
sprite('markerHouse'),
|
||||
scale(TILE * 2/3),
|
||||
pos(SCALE/10, SCALE/10),
|
||||
z(Z.top),
|
||||
area(),
|
||||
rotate(3),
|
||||
"menu",
|
||||
"navButton",
|
||||
]);
|
||||
|
||||
|
||||
/*
|
||||
EEEEEE
|
||||
EEEEEEEEEEE
|
||||
|
||||
Main Content
|
||||
(grammar mode enabled)
|
||||
|
||||
EEEEEEEEEEE
|
||||
EEEEEE
|
||||
*/
|
||||
|
||||
let achKeys = Object.keys(ACHIEVEMENTS);
|
||||
let achLength = achKeys.length;
|
||||
|
||||
for (let i = 0; i < achLength; i++) {
|
||||
let rowMod = 8;
|
||||
let sy = SCALE*(2.7 + 1.1*Math.floor(i / rowMod));
|
||||
if (STUFF.achievements.includes(achKeys[i])) {
|
||||
for (let l = 0; l < 2; l++) {
|
||||
if (!(ACHIEVEMENTS[achKeys[i]].icon[1] == -1 && l == 0)) {
|
||||
add([
|
||||
sprite(['banner', 'achievements'][l], { frame: (ACHIEVEMENTS[achKeys[i]].icon[1-l]) }),
|
||||
pos(SCALE*(1.15 + 1.1*(i % rowMod)), sy),
|
||||
origin('center'),
|
||||
scale(TILE*0.8),
|
||||
z(Z.main + l),
|
||||
"scrollable",
|
||||
{
|
||||
startY: sy,
|
||||
}
|
||||
]);
|
||||
};
|
||||
};
|
||||
} else {
|
||||
add([
|
||||
circle(SCALE*0.2),
|
||||
pos(SCALE*(1.15 + 1.1*(i % rowMod)), sy),
|
||||
origin('center'),
|
||||
color(BLACK),
|
||||
opacity(0.15),
|
||||
z(Z.main),
|
||||
"scrollable",
|
||||
{
|
||||
startY: sy,
|
||||
}
|
||||
]);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
onClick('menu', (m) => {
|
||||
fadeOut();
|
||||
setTimeout(() => { go('menu'); }, FADE_TIME);
|
||||
});
|
||||
|
||||
let startHold = 0;
|
||||
let startScroll = 0;
|
||||
let scrollDiff = 0;
|
||||
let holdWait = true;
|
||||
|
||||
onUpdate(() => {
|
||||
if (isMouseDown()) {
|
||||
if (holdWait) {
|
||||
holdWait = false;
|
||||
startHold = mousePos().y / SCALE;
|
||||
scrollDiff = 0;
|
||||
startScroll = mainScroll;
|
||||
};
|
||||
|
||||
scrollDiff = startHold - mousePos().y / SCALE;
|
||||
mainScroll = Math.max(0, Math.min(2, startScroll + scrollDiff));
|
||||
|
||||
} else {
|
||||
holdWait = true;
|
||||
};
|
||||
|
||||
every('navButton', (o) => {
|
||||
o.scale = o.isHovering() ? vec2(TILE*0.73) : vec2(TILE*2/3);
|
||||
});
|
||||
every('scrollable', (s) => {
|
||||
s.pos.y = s.startY - mainScroll*SCALE;
|
||||
});
|
||||
});
|
||||
|
||||
});
|
908
ballisticchickens/code/game.js
Normal file
@ -0,0 +1,908 @@
|
||||
const STUFF = getData('save', {
|
||||
money: 0,
|
||||
upgrades: [0,0,0,0,0,0],
|
||||
achievements: [],
|
||||
});
|
||||
|
||||
var debugMode = false;
|
||||
debug.inspect = false;
|
||||
|
||||
function shortNum(x) {
|
||||
x = Math.floor(x);
|
||||
let letters = ['M', 'B', 'T', 'QA', 'QI', 'SX', 'SP', 'O', 'N', 'D'];
|
||||
let len = letters.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
let pow = (len-i)*3 + 3;
|
||||
if (x >= 10**pow) {
|
||||
return `${(x/10**pow).toFixed(1)}${letters[len-1-i]}`;
|
||||
};
|
||||
};
|
||||
return x.toLocaleString('en-US')
|
||||
};
|
||||
|
||||
function achieve(x) {
|
||||
if (!STUFF.achievements.includes(x)) {
|
||||
STUFF.achievements.push(x);
|
||||
setData('save', STUFF);
|
||||
};
|
||||
};
|
||||
|
||||
scene('game', () => {
|
||||
if (STUFF.achievements == undefined)
|
||||
STUFF.achievements = [];
|
||||
|
||||
console.log(STUFF)
|
||||
|
||||
const Z = {
|
||||
bg: 0,
|
||||
game: 100,
|
||||
player: 200,
|
||||
ui: 300,
|
||||
shade: 400,
|
||||
endBtns: 500,
|
||||
black: 600,
|
||||
};
|
||||
|
||||
var score = 0;
|
||||
var fuel = 50 + upgradeMod(2);
|
||||
var maxFuel = fuel;
|
||||
|
||||
var distace = 0;
|
||||
var distanceF = 0;
|
||||
var altitude = 0;
|
||||
var maxAltitude = 0;
|
||||
var velocity = 0;
|
||||
var velocityMach = 0;
|
||||
|
||||
var lastStar = 0;
|
||||
var lastCleanup = 0;
|
||||
|
||||
var chickenShot = false;
|
||||
var groundHit = false;
|
||||
var stopped = false;
|
||||
var endMenuShown = false;
|
||||
var fadingOut = false;
|
||||
var fireworkDetatched = false;
|
||||
var rolling = false;
|
||||
|
||||
var starsRendered = 0;
|
||||
var starsPossible = 0;
|
||||
var debugZoomNum = 0;
|
||||
var debugZoom = 1;
|
||||
|
||||
const bgRect = add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
z(Z.bg),
|
||||
opacity(1),
|
||||
color(rgb(100,200,250)),
|
||||
fixed(),
|
||||
]);
|
||||
|
||||
const black = add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
z(Z.black),
|
||||
opacity(1),
|
||||
color(BLACK),
|
||||
fixed(),
|
||||
]);
|
||||
|
||||
for (let f = 0; f < 20; f++) {
|
||||
setTimeout(() => {
|
||||
black.opacity -= 0.05;
|
||||
}, f*15);
|
||||
};
|
||||
|
||||
function fadeOut() {
|
||||
if (!fadingOut) {
|
||||
fadingOut = true;
|
||||
for (let f = 0; f < 20; f++) {
|
||||
setTimeout(() => {
|
||||
black.opacity += 0.05;
|
||||
}, f * FADE_TIME / 15);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const cannon = add([
|
||||
sprite('cannon'),
|
||||
pos(SCALE, height() - SCALE*0.85),
|
||||
origin('botleft'),
|
||||
scale(TILE),
|
||||
z(Z.player),
|
||||
]);
|
||||
|
||||
const chicken = add([
|
||||
sprite('chicken'),
|
||||
pos(0, height()*2),
|
||||
origin('center'),
|
||||
scale(TILE),
|
||||
area(),
|
||||
z(Z.player),
|
||||
rotate(0),
|
||||
'chicken',
|
||||
{
|
||||
xv: -1,
|
||||
yv: -1,
|
||||
},
|
||||
]);
|
||||
|
||||
const rocket = add([
|
||||
sprite('rocket'),
|
||||
pos(0, height()*2),
|
||||
origin('center'),
|
||||
scale(TILE),
|
||||
area(),
|
||||
z(Z.player),
|
||||
rotate(0),
|
||||
opacity(1),
|
||||
]);
|
||||
|
||||
const vaporCone = add([
|
||||
sprite('vaporCone'),
|
||||
pos(0, height()*2),
|
||||
origin('center'),
|
||||
scale(TILE),
|
||||
z(Z.player),
|
||||
rotate(0),
|
||||
opacity(1),
|
||||
]);
|
||||
|
||||
function detatchAnim() {
|
||||
if (!fireworkDetatched) {
|
||||
fireworkDetatched = true;
|
||||
for (let i = 0; i < 10; i++) {
|
||||
setTimeout(() => {
|
||||
rocket.opacity -= 0.1;
|
||||
}, i*50);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
let border = SCALE*0.027;
|
||||
let xOff = Math.sin( (Math.PI * i) /4 ) *border;
|
||||
let yOff = Math.cos( (Math.PI * i) /4 ) *border;
|
||||
if (i == 0) { xOff = 0; yOff = 0; };
|
||||
add([
|
||||
text(`0m travelled`, {
|
||||
size: SCALE*0.6,
|
||||
font: 'ubuntu',
|
||||
}),
|
||||
pos(width() - SCALE/10 +xOff, SCALE/10 +yOff),
|
||||
z(Z.ui +(i == 0 ? 2:1)),
|
||||
color(i == 0 ? WHITE:BLACK),
|
||||
fixed(),
|
||||
origin('topright'),
|
||||
"distanceText",
|
||||
]);
|
||||
};
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
let border = SCALE*0.05;
|
||||
let xOff = Math.sin( (Math.PI * i) /4 ) *border;
|
||||
let yOff = Math.cos( (Math.PI * i) /4 ) *border;
|
||||
if (i == 0) { xOff = 0; yOff = 0; };
|
||||
add([
|
||||
text(`0`, {
|
||||
size: SCALE,
|
||||
font: 'rubik',
|
||||
}),
|
||||
pos(SCALE/7 +xOff, SCALE/7 +yOff),
|
||||
z(Z.ui +(i == 0 ? 2:1)),
|
||||
color(i == 0 ? WHITE:BLACK),
|
||||
fixed(),
|
||||
"scoreText",
|
||||
]);
|
||||
};
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
let border = SCALE*0.016;
|
||||
let xOff = Math.sin( (Math.PI * i) /4 ) *border;
|
||||
let yOff = Math.cos( (Math.PI * i) /4 ) *border;
|
||||
if (i == 0) { xOff = 0; yOff = 0; };
|
||||
add([
|
||||
text(`Altitude: 0m`, {
|
||||
size: SCALE*0.25,
|
||||
font: 'ubuntu',
|
||||
}),
|
||||
pos(width() - SCALE/10 +xOff, SCALE*(0.7 + 1/7) +yOff),
|
||||
z(Z.ui +(i == 0 ? 2:1)),
|
||||
color(i == 0 ? WHITE:BLACK),
|
||||
fixed(),
|
||||
origin('topright'),
|
||||
"altitudeText",
|
||||
]);
|
||||
};
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
let border = SCALE*0.016;
|
||||
let xOff = Math.sin( (Math.PI * i) /4 ) *border;
|
||||
let yOff = Math.cos( (Math.PI * i) /4 ) *border;
|
||||
if (i == 0) { xOff = 0; yOff = 0; };
|
||||
add([
|
||||
text(`Top Altitude: 0m`, {
|
||||
size: SCALE*0.18,
|
||||
font: 'ubuntu',
|
||||
}),
|
||||
pos(width() - SCALE/10 +xOff, SCALE*(1.05 + 1/7) +yOff),
|
||||
z(Z.ui +(i == 0 ? 2:1)),
|
||||
color(i == 0 ? WHITE:BLACK),
|
||||
fixed(),
|
||||
origin('topright'),
|
||||
"maxAltitudeText",
|
||||
]);
|
||||
};
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
let border = SCALE*0.016;
|
||||
let xOff = Math.sin( (Math.PI * i) /4 ) *border;
|
||||
let yOff = Math.cos( (Math.PI * i) /4 ) *border;
|
||||
if (i == 0) { xOff = 0; yOff = 0; };
|
||||
add([
|
||||
text(`Velocity: 0 m/s`, {
|
||||
size: SCALE*0.18,
|
||||
font: 'ubuntu',
|
||||
}),
|
||||
pos(width() - SCALE/10 +xOff, SCALE*(1.5 + 1/7) +yOff),
|
||||
z(Z.ui +(i == 0 ? 2:1)),
|
||||
color(i == 0 ? WHITE:BLACK),
|
||||
fixed(),
|
||||
origin('topright'),
|
||||
"velocityText",
|
||||
]);
|
||||
};
|
||||
|
||||
add([
|
||||
pos(SCALE/7, SCALE*(1 + 1/7)),
|
||||
rect(SCALE*2, SCALE*0.3),
|
||||
color(BLACK),
|
||||
fixed(),
|
||||
z(Z.ui),
|
||||
]);
|
||||
|
||||
add([
|
||||
pos(SCALE/7, SCALE*(1 + 1/7)),
|
||||
rect(SCALE*0.5, SCALE*0.5),
|
||||
color(BLACK),
|
||||
fixed(),
|
||||
z(Z.ui),
|
||||
'fuelLabel',
|
||||
]);
|
||||
|
||||
add([
|
||||
pos(SCALE*(0.04 + 1/7), SCALE*(1.04 + 1/7)),
|
||||
rect(SCALE*1.92, SCALE*0.22),
|
||||
color(rgb(80,80,80)),
|
||||
fixed(),
|
||||
z(Z.ui),
|
||||
]);
|
||||
|
||||
const fuelValue = add([
|
||||
pos(SCALE*(0.04 + 1/7), SCALE*(1.04 + 1/7)),
|
||||
rect(SCALE*1.92, SCALE*0.22),
|
||||
color(rgb(255,255,0)),
|
||||
fixed(),
|
||||
z(Z.ui),
|
||||
]);
|
||||
|
||||
add([
|
||||
text('FUEL', { font: 'rubik', size: SCALE*0.13 }),
|
||||
pos(SCALE*(0.09 + 1/7), SCALE*(1.33 + 1/7)),
|
||||
color(WHITE),
|
||||
z(Z.ui),
|
||||
fixed(),
|
||||
]);
|
||||
|
||||
const groundFix = add([
|
||||
rect(width()*2, SCALE*2),
|
||||
pos(-width()/2, height()-SCALE*0.9),
|
||||
color(rgb(100,60,0)),
|
||||
z(Z.bg),
|
||||
]);
|
||||
|
||||
for (let i = 0; i < 12; i++) {
|
||||
add([
|
||||
sprite('ground'),
|
||||
pos(SCALE * i, height()),
|
||||
origin('botright'),
|
||||
scale(TILE),
|
||||
z(Z.game),
|
||||
'ground',
|
||||
]);
|
||||
};
|
||||
|
||||
onClick(() => {
|
||||
if (!chickenShot) {
|
||||
chickenShot = true;
|
||||
chicken.pos = cannon.pos.add(SCALE/2, -SCALE/2);
|
||||
|
||||
let launchVel = 10 + upgradeMod(0);
|
||||
chicken.xv = launchVel;
|
||||
chicken.yv = launchVel;
|
||||
|
||||
cannon.frame++;
|
||||
wait(0.2, () => { cannon.frame++; });
|
||||
};
|
||||
});
|
||||
|
||||
onKeyPress('space', () => {
|
||||
if (!chickenShot) {
|
||||
chickenShot = true;
|
||||
chicken.pos = cannon.pos.add(SCALE/2, -SCALE/2);
|
||||
|
||||
let launchVel = 10 + upgradeMod(0);
|
||||
chicken.xv = launchVel;
|
||||
chicken.yv = launchVel;
|
||||
|
||||
cannon.frame++;
|
||||
wait(0.2, () => { cannon.frame++; });
|
||||
};
|
||||
});
|
||||
|
||||
onCollide('chicken', 'star', (c,s) => {
|
||||
score += s.value;
|
||||
destroy(s);
|
||||
});
|
||||
|
||||
onCollide('chicken', 'trampoline', (c, t) => {
|
||||
if (!rolling && !t.used) {
|
||||
t.used = true;
|
||||
score += 5;
|
||||
chicken.yv = Math.abs(0.9 * chicken.yv);
|
||||
add([
|
||||
text('+5', {
|
||||
size: SCALE*0.6,
|
||||
font: 'rubik',
|
||||
align: 'center',
|
||||
}),
|
||||
pos(toScreen(c.pos)),
|
||||
color(rgb(255,255,100)),
|
||||
lifespan(0.5, { fade: 0.5 }),
|
||||
origin('center'),
|
||||
fixed(),
|
||||
]);
|
||||
};
|
||||
});
|
||||
|
||||
every('fuelLabel', (f) => { f.radius = SCALE/10; });
|
||||
|
||||
onKeyPress('e', () => {
|
||||
showEndMenu();
|
||||
});
|
||||
|
||||
function upgradeMod(x) {
|
||||
return STUFF.upgrades[x] * OFFERS[x].gain;
|
||||
};
|
||||
|
||||
function getScore(x) {
|
||||
return (Math.log(x) / Math.log(1.5) /5) + 1 + x/30;
|
||||
};
|
||||
|
||||
var collectableSizes = [
|
||||
0.5, 0.5, 0.5, 0.5, 0.5, 0.5,
|
||||
0.9, 0.9, 0.9, 0.9,
|
||||
1.3, 1.3, 1.3, 1.3,
|
||||
];
|
||||
|
||||
|
||||
onUpdate(() => {
|
||||
if (chickenShot && !stopped) {
|
||||
chicken.pos = chicken.pos.add(
|
||||
chicken.xv *SCALE *dt(),
|
||||
-chicken.yv *SCALE *dt()
|
||||
);
|
||||
|
||||
velocity = Math.sqrt(chicken.xv**2 + chicken.yv**2);
|
||||
velocityMach = (Math.sqrt(chicken.xv**2 + chicken.yv**2) / 343).toLocaleString('en-US');
|
||||
|
||||
if (chicken.pos.y >= height()-SCALE*1.1) {
|
||||
chicken.pos.y = height()-SCALE*1.1;
|
||||
chicken.yv *= -(-50/(upgradeMod(3)+50) + 1.3);
|
||||
if (!rolling) chicken.xv *= -50/(upgradeMod(3)+50) + 1.5;
|
||||
|
||||
if (Math.abs(chicken.yv) <= 0.5) {
|
||||
chicken.yv = 0;
|
||||
rolling = true;
|
||||
if (Math.abs(chicken.xv) <= 0.5) {
|
||||
chicken.xv = 0;
|
||||
};
|
||||
};
|
||||
|
||||
if (!groundHit) {
|
||||
groundHit = true;
|
||||
fuel = 0
|
||||
chicken.frame++;
|
||||
detatchAnim();
|
||||
};
|
||||
};
|
||||
|
||||
chicken.yv -= (50 * 16*dt()) / (upgradeMod(1) + 50);
|
||||
if (rolling) {
|
||||
if (chicken.xv != 0) {
|
||||
chicken.xv -= (30 * dt()*1.3) / (upgradeMod(1) + 30);
|
||||
};
|
||||
} else {
|
||||
chicken.xv -= (30 * dt()) / (upgradeMod(1) + 30);
|
||||
};
|
||||
|
||||
if (chicken.xv > 0) {
|
||||
if (groundHit && !rolling) {
|
||||
chicken.angle += dt()*500;
|
||||
} else if (!rolling) {
|
||||
chicken.angle = Math.atan2(-chicken.yv, chicken.xv)*57;
|
||||
};
|
||||
if (rolling) {
|
||||
chicken.angle += dt() * chicken.xv*120;
|
||||
};
|
||||
};
|
||||
|
||||
if (chicken.xv == 0 && !stopped) {
|
||||
stopped = true;
|
||||
wait(0.1, () => {
|
||||
chicken.angle = 0;
|
||||
setTimeout(showEndMenu, 300);
|
||||
});
|
||||
};
|
||||
|
||||
if (Math.abs(chicken.xv) <= 0.2)
|
||||
chicken.xv = 0;
|
||||
|
||||
distanceF = (chicken.pos.x / SCALE);
|
||||
every('distanceText', (d) => { d.text = `${shortNum(distanceF)}m travelled`; });
|
||||
distance = Math.floor(distanceF);
|
||||
|
||||
altitude = ((height()-SCALE*1.1-chicken.pos.y) / SCALE);
|
||||
every('altitudeText', (a) => { a.text = `Altitude: ${shortNum(altitude)}m`; });
|
||||
|
||||
maxAltitude = Math.max(maxAltitude, altitude);
|
||||
every('maxAltitudeText', (m) => { m.text = `Top Altitude: ${shortNum(maxAltitude)}m`; });
|
||||
|
||||
every('velocityText', (v) => {
|
||||
let val = (velocityMach >= 0.8 ? `Mach ${parseFloat(velocityMach).toFixed(1)}` : `${shortNum(velocity)} m/s`);
|
||||
v.text = `Velocity: ${val}`;
|
||||
});
|
||||
|
||||
every('scoreText', (s) => { s.text = score; });
|
||||
fuel = Math.max(0, fuel);
|
||||
|
||||
camPos(vec2(
|
||||
Math.max(center().x, chicken.pos.x),
|
||||
Math.min(center().y, chicken.pos.y),
|
||||
));
|
||||
|
||||
|
||||
// if (distance >=)
|
||||
|
||||
|
||||
// STARS (and more) SPAWNING MESS
|
||||
|
||||
if (distance % 2 == 0 && lastStar != distance) {
|
||||
lastStar = distance;
|
||||
starsRendered = 0;
|
||||
starsPossible = 0;
|
||||
for (let s = 0; s < STAR_TYPES.length; s++) {
|
||||
let current = STAR_TYPES[s];
|
||||
for (let i = 0; i < current.count; i++) {
|
||||
starsPossible++;
|
||||
let starHeight = rand(current.range[0], current.range[1]);
|
||||
if (Math.max(Math.abs(chicken.yv), 10)
|
||||
>
|
||||
Math.abs(starHeight - altitude - chicken.yv)) {
|
||||
starsRendered++;
|
||||
if (current.frame == 'not a star lol') {
|
||||
add([
|
||||
sprite('cloud'),
|
||||
scale(TILE * rand(5,14)),
|
||||
origin('center'),
|
||||
area(),
|
||||
pos((distance+10+i)*SCALE, height()- SCALE*starHeight),
|
||||
opacity(0.3),
|
||||
z(Z.game -1),
|
||||
'skyObject',
|
||||
]);
|
||||
} else {
|
||||
add([
|
||||
sprite('collectables', { frame: current.frame }),
|
||||
scale(TILE * collectableSizes[current.frame]),
|
||||
origin('center'),
|
||||
area(),
|
||||
pos((distance+10+i)*SCALE, height()- SCALE*starHeight),
|
||||
z(Z.game),
|
||||
'star',
|
||||
'skyObject',
|
||||
{ value: current.value },
|
||||
]);
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (rand(0,100) < 15) {
|
||||
add([
|
||||
sprite('flora', {
|
||||
frame: randi(0,3),
|
||||
flipX: rand(0,100) < 50 ? true : false,
|
||||
}),
|
||||
scale(TILE * rand(0.7, 1)),
|
||||
origin('botleft'),
|
||||
pos((distance+10)*SCALE, height() - SCALE * rand(0.8, 0.9)),
|
||||
z(Z.game),
|
||||
]);
|
||||
};
|
||||
|
||||
if (rand(0,100) < 4 + upgradeMod(4)) {
|
||||
add([
|
||||
sprite('trampoline'),
|
||||
scale(TILE*1.9),
|
||||
origin('botleft'),
|
||||
area({ height: 160 }),
|
||||
pos((distance+10)*SCALE, height()-SCALE*0.75),
|
||||
z(Z.game +1),
|
||||
"trampoline",
|
||||
{
|
||||
used: false,
|
||||
}
|
||||
]);
|
||||
};
|
||||
};
|
||||
|
||||
// end of spawning
|
||||
|
||||
if (isMouseDown() || isKeyDown('space')) {
|
||||
if (fuel > 0) {
|
||||
shake(SCALE/12);
|
||||
chicken.yv += 0.8 * (1+upgradeMod(5));
|
||||
chicken.xv += 0.3 * (1+upgradeMod(5));
|
||||
fuel -= 60*dt();
|
||||
rocket.frame = 1;
|
||||
add([
|
||||
circle(SCALE*0.1),
|
||||
color(rgb(100,100,100)),
|
||||
lifespan(0.2, { fade: 0.2 }),
|
||||
pos(chicken.pos.add(
|
||||
SCALE*rand(-0.1, 0.1),
|
||||
SCALE*rand(-0.1, 0.1),
|
||||
)),
|
||||
]);
|
||||
} else {
|
||||
detatchAnim();
|
||||
rocket.frame = 0;
|
||||
};
|
||||
} else {
|
||||
rocket.frame = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// end of chicken motion thingy idk
|
||||
|
||||
every('ground', (g) => {
|
||||
if (camPos().sub(center()).x >= g.pos.x+SCALE) {
|
||||
g.pos.x += SCALE*12;
|
||||
};
|
||||
});
|
||||
|
||||
let flooredTime = Math.floor(time()*3);
|
||||
if (flooredTime != lastCleanup) {
|
||||
lastCleanup = flooredTime;
|
||||
every('skyObject', (s) => {
|
||||
if (s.pos.x <= chicken.pos.x - SCALE*7) {
|
||||
destroy(s);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
let n = -0.28;
|
||||
rocket.pos = chicken.pos.add(
|
||||
Math.sin((chicken.angle+90) /57)*SCALE*n,
|
||||
-Math.cos((chicken.angle+90) /57)*SCALE*n,
|
||||
);
|
||||
rocket.angle = chicken.angle;
|
||||
|
||||
vaporCone.pos = chicken.pos;
|
||||
vaporCone.angle = chicken.angle;
|
||||
vaporCone.opacity = Math.max(0, -0.16 * Math.abs(velocity - 343) + 1);
|
||||
|
||||
groundFix.pos.x = -width() + camPos().x;
|
||||
|
||||
let blackSky1 = 30000;
|
||||
let blackSky2 = blackSky1 * 0.6;
|
||||
bgRect.color = rgb(
|
||||
Math.max(0, (blackSky2 - altitude) / blackSky2 * 100),
|
||||
Math.max(0, (blackSky2 - altitude) / blackSky2 * 200),
|
||||
Math.max(0, (blackSky1 - altitude) / blackSky1 * 255),
|
||||
);
|
||||
|
||||
every('btnOutline', (o) => {
|
||||
o.color = o.isHovering() ? WHITE : BLACK;
|
||||
});
|
||||
|
||||
fuelValue.width = SCALE*1.92 * (fuel / maxFuel);
|
||||
|
||||
if (fuel <= maxFuel/5) {
|
||||
fuelValue.color = Math.floor(time()*10) % 2 == 0 ? YELLOW : RED;
|
||||
} else {
|
||||
fuelValue.color = YELLOW;
|
||||
};
|
||||
|
||||
if (debugMode) {
|
||||
if (isKeyDown('z')) {
|
||||
debugZoomNum += 1*dt();
|
||||
debugZoom = Math.cos(debugZoomNum)/2.5 +0.6;
|
||||
camScale(debugZoom);
|
||||
};
|
||||
} else {
|
||||
camScale(Math.max(Math.min(
|
||||
(-1/3000) * altitude + 1 + (20/3000)
|
||||
, 1), 0.35));
|
||||
};
|
||||
|
||||
|
||||
if (debugMode)
|
||||
debug.log(` add: ${starsRendered} / ${starsPossible} \n obj: ${debug.objCount()}\n fps: ${debug.fps()} ( -${60-debug.fps()} ) \nzoom: ${debugZoom.toFixed(1)}`)
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////
|
||||
/////////////////////////
|
||||
/////////////////////////
|
||||
/////////////////////////
|
||||
/////////////////////////
|
||||
/////////////////////////
|
||||
/////////////////////////
|
||||
|
||||
|
||||
function showEndMenu() {
|
||||
stopped = true;
|
||||
if (!endMenuShown) {
|
||||
endMenuShown = true;
|
||||
add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
fixed(),
|
||||
color(BLACK),
|
||||
opacity(0.4),
|
||||
z(Z.shade),
|
||||
]);
|
||||
|
||||
const endBack = add([
|
||||
rect(width()*0.8, height()*0.8),
|
||||
pos(center()),
|
||||
fixed(),
|
||||
color(BLACK),
|
||||
opacity(0.75),
|
||||
origin('center'),
|
||||
scale(0),
|
||||
z(Z.shade),
|
||||
]);
|
||||
endBack.radius = SCALE/3;
|
||||
|
||||
for (let i = 0; i < 20; i++) {
|
||||
setTimeout(() => {
|
||||
endBack.scale = endBack.scale.add(0.05, 0.05);
|
||||
}, i*10);
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
add([
|
||||
text('Flight complete!', {
|
||||
align: 'center',
|
||||
size: SCALE*0.75,
|
||||
font: 'rubik',
|
||||
}),
|
||||
pos(width()/2, SCALE*1.5),
|
||||
origin('center'),
|
||||
z(Z.endBtns),
|
||||
fixed(),
|
||||
scale(vec2(1.11, 1)),
|
||||
opacity(0),
|
||||
'endUI',
|
||||
]);
|
||||
|
||||
add([
|
||||
rect(SCALE*3.25, SCALE*0.75),
|
||||
pos(SCALE*4.725, SCALE*4.175),
|
||||
origin('topright'),
|
||||
color(BLACK),
|
||||
z(Z.endBtns-1),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
area(),
|
||||
'endUI',
|
||||
'endBtn',
|
||||
'btnOutline',
|
||||
]);
|
||||
|
||||
const retryBtn = add([
|
||||
rect(SCALE*3.2, SCALE*0.7),
|
||||
pos(SCALE*4.7, SCALE*4.2),
|
||||
origin('topright'),
|
||||
color(rgb(0,160,0)),
|
||||
z(Z.endBtns),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
area(),
|
||||
'endUI',
|
||||
'endBtn',
|
||||
'retry'
|
||||
]);
|
||||
|
||||
add([
|
||||
rect(SCALE*3.0, SCALE*0.5),
|
||||
pos(SCALE*4.6, SCALE*4.3),
|
||||
origin('topright'),
|
||||
color(rgb(0,200,0)),
|
||||
z(Z.endBtns),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
'endUI',
|
||||
'endBtn',
|
||||
]);
|
||||
|
||||
add([
|
||||
text('RETRY', {
|
||||
align: 'center',
|
||||
width: SCALE*3,
|
||||
size: SCALE*0.4,
|
||||
font: 'manrope',
|
||||
letterSpacing: SCALE*0.03,
|
||||
}),
|
||||
pos(SCALE*4.6, SCALE*4.38),
|
||||
origin('topright'),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
z(Z.endBtns),
|
||||
'endUI'
|
||||
]);
|
||||
|
||||
const shopBtn = add([
|
||||
rect(SCALE*3.2, SCALE*0.7),
|
||||
pos(SCALE*5.3, SCALE*4.2),
|
||||
origin('topleft'),
|
||||
color(rgb(80,80,80)),
|
||||
z(Z.endBtns),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
area(),
|
||||
'endUI',
|
||||
'endBtn',
|
||||
'shop'
|
||||
]);
|
||||
|
||||
add([
|
||||
rect(SCALE*3.25, SCALE*0.75),
|
||||
pos(SCALE*5.275, SCALE*4.175),
|
||||
origin('topleft'),
|
||||
color(BLACK),
|
||||
z(Z.endBtns-1),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
area(),
|
||||
'endUI',
|
||||
'endBtn',
|
||||
'btnOutline',
|
||||
]);
|
||||
|
||||
add([
|
||||
rect(SCALE*3.0, SCALE*0.5),
|
||||
pos(SCALE*5.4, SCALE*4.3),
|
||||
origin('topleft'),
|
||||
color(rgb(100,100,100)),
|
||||
z(Z.endBtns),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
'endUI',
|
||||
'endBtn',
|
||||
]);
|
||||
|
||||
add([
|
||||
text('SHOP', {
|
||||
align: 'center',
|
||||
width: SCALE*3,
|
||||
size: SCALE*0.4,
|
||||
font: 'manrope',
|
||||
letterSpacing: SCALE*0.03,
|
||||
}),
|
||||
pos(SCALE*5.4, SCALE*4.38),
|
||||
origin('topleft'),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
z(Z.endBtns),
|
||||
'endUI'
|
||||
]);
|
||||
|
||||
every('endBtn', (b) => {
|
||||
b.radius = SCALE/5;
|
||||
});
|
||||
|
||||
let moneyGain = Math.floor(
|
||||
score/2 +
|
||||
getScore(distanceF -16) +
|
||||
getScore(maxAltitude -3)
|
||||
);
|
||||
if (moneyGain.toString() == 'NaN') moneyGain = 0;
|
||||
|
||||
STUFF.money += moneyGain;
|
||||
|
||||
let somethingAffordable = false;
|
||||
|
||||
for (let i = 0; i < OFFERS.length; i++) {
|
||||
somethingAffordable = (truePrice(i) <= STUFF.money);
|
||||
if (somethingAffordable) break;
|
||||
};
|
||||
|
||||
if (somethingAffordable) {
|
||||
add([
|
||||
sprite('attention'),
|
||||
pos(SCALE*8.435, SCALE*4.275),
|
||||
origin('center'),
|
||||
scale(TILE/4),
|
||||
z(Z.endBtns +3),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
'endUI',
|
||||
]);
|
||||
};
|
||||
|
||||
add([
|
||||
text(`Distance: \nApogee: \nPoints: \nMoney Gained: \n\nBalance:`, {
|
||||
size: SCALE*0.27,
|
||||
align: 'left',
|
||||
width: SCALE*2.5,
|
||||
font: 'ubuntu',
|
||||
lineSpacing: SCALE*0.05,
|
||||
letterSpacing: SCALE*0.01,
|
||||
}),
|
||||
pos(center().sub(2*SCALE, 0)),
|
||||
origin('center'),
|
||||
z(Z.endBtns),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
'endUI',
|
||||
]);
|
||||
|
||||
add([
|
||||
text(`${shortNum(parseFloat(parseFloat(distanceF).toFixed(1)))}m\n ${shortNum(parseFloat(parseFloat(maxAltitude).toFixed(1)))}m\n ${shortNum(score)}\n +$${shortNum(moneyGain)}\n\n $${shortNum(STUFF.money)}`, {
|
||||
size: SCALE*0.27,
|
||||
align: 'right',
|
||||
width: SCALE*5,
|
||||
font: 'ubuntu',
|
||||
lineSpacing: SCALE*0.05,
|
||||
letterSpacing: SCALE*0.01,
|
||||
}),
|
||||
pos(center().add(0.75*SCALE, 0)),
|
||||
origin('center'),
|
||||
z(Z.endBtns),
|
||||
color(rgb(0,255,0)),
|
||||
fixed(),
|
||||
opacity(0),
|
||||
'endUI',
|
||||
]);
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
setTimeout(() => {
|
||||
every('endUI', (e) => {
|
||||
e.opacity += 0.1;
|
||||
});
|
||||
}, i*15);
|
||||
};
|
||||
|
||||
setData('save', STUFF);
|
||||
|
||||
onClick('retry', (r) => {
|
||||
fadeOut();
|
||||
setTimeout(() => { go('retry'); }, FADE_TIME);
|
||||
});
|
||||
|
||||
onClick('shop', (r) => {
|
||||
fadeOut();
|
||||
setTimeout(() => { go('shop'); }, FADE_TIME);
|
||||
});
|
||||
}, 200);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
});
|
81
ballisticchickens/code/help.js
Normal file
@ -0,0 +1,81 @@
|
||||
scene('help', () => {
|
||||
const Z = {
|
||||
bg: 0,
|
||||
text: 100,
|
||||
black: 200,
|
||||
};
|
||||
|
||||
const tutorialText = [
|
||||
'# wewe',
|
||||
'fbhfbsdhdhsh',
|
||||
'AAA oui',
|
||||
'# goAd placeholder',
|
||||
'aeAgh'
|
||||
];
|
||||
|
||||
add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
z(Z.bg),
|
||||
opacity(1),
|
||||
color(rgb(110,65,30)),
|
||||
fixed(),
|
||||
]);
|
||||
|
||||
const black = add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
z(Z.black),
|
||||
opacity(1),
|
||||
color(BLACK),
|
||||
fixed(),
|
||||
]);
|
||||
|
||||
for (let f = 0; f < 20; f++) {
|
||||
setTimeout(() => {
|
||||
black.opacity -= 0.05;
|
||||
}, f*15);
|
||||
};
|
||||
|
||||
let fadingOut = false;
|
||||
function fadeOut() {
|
||||
if (!fadingOut) {
|
||||
fadingOut = true;
|
||||
for (let f = 0; f < 20; f++) {
|
||||
setTimeout(() => {
|
||||
black.opacity += 0.05;
|
||||
}, f * FADE_TIME / 20);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
let textHeight = 0;
|
||||
for (let i = 0; i < tutorialText.length; i++) {
|
||||
let txt = tutorialText[i].replace('# ', '');
|
||||
let isTitle = !(tutorialText[i] == txt);
|
||||
let p = vec2(
|
||||
0,
|
||||
SCALE * (textHeight + (isTitle ? 0.3 : 0))
|
||||
);
|
||||
let shadow = isTitle ? 0.04 : 0.027;
|
||||
add([
|
||||
text(txt, {
|
||||
size: SCALE*(isTitle ? 0.7 : 0.3),
|
||||
font: isTitle ? 'rubik' : 'ubuntu',
|
||||
}),
|
||||
pos(p.add(SCALE*shadow, SCALE*shadow)),
|
||||
color(BLACK),
|
||||
z(Z.text),
|
||||
]);
|
||||
add([
|
||||
text(txt, {
|
||||
size: SCALE*(isTitle ? 0.7 : 0.3),
|
||||
font: isTitle ? 'rubik' : 'ubuntu',
|
||||
}),
|
||||
pos(p),
|
||||
color(WHITE),
|
||||
z(Z.text),
|
||||
]);
|
||||
textHeight += isTitle ? 1.1 : 0.4;
|
||||
}
|
||||
});
|
166
ballisticchickens/code/menu.js
Normal file
@ -0,0 +1,166 @@
|
||||
scene('menu', () => {
|
||||
const Z = {
|
||||
bg: 0,
|
||||
ui: 100,
|
||||
black: 200,
|
||||
};
|
||||
|
||||
add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
color(rgb(100,200,250)),
|
||||
]);
|
||||
|
||||
const black = add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
z(Z.black),
|
||||
opacity(1),
|
||||
color(BLACK),
|
||||
fixed(),
|
||||
]);
|
||||
|
||||
for (let f = 0; f < 20; f++) {
|
||||
setTimeout(() => {
|
||||
black.opacity -= 0.05;
|
||||
}, f*15);
|
||||
};
|
||||
|
||||
let fadingOut = false;
|
||||
function fadeOut() {
|
||||
if (!fadingOut) {
|
||||
fadingOut = true;
|
||||
for (let f = 0; f < 20; f++) {
|
||||
setTimeout(() => {
|
||||
black.opacity += 0.05;
|
||||
}, f * FADE_TIME / 20);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
add([
|
||||
sprite('logo'),
|
||||
pos(center().sub(0, SCALE*0.9)),
|
||||
origin('center'),
|
||||
scale(TILE*7),
|
||||
z(Z.ui),
|
||||
]);
|
||||
|
||||
for (let i = 0; i < 1; i++) {
|
||||
let btnPos = vec2(center().add(0, SCALE*(0.9 + i)));
|
||||
|
||||
add([
|
||||
text([(window.self == window.top ? 'PLAY' : 'OPEN'), 'HELP'][i], {
|
||||
align: 'center',
|
||||
size: SCALE*0.4,
|
||||
font: 'manrope',
|
||||
}),
|
||||
pos(btnPos.add(0, SCALE*0.03)),
|
||||
origin('center'),
|
||||
color(WHITE),
|
||||
z(Z.ui +1),
|
||||
])
|
||||
|
||||
add([
|
||||
rect(SCALE*3.25, SCALE*0.75),
|
||||
pos(btnPos),
|
||||
origin('center'),
|
||||
color(BLACK),
|
||||
z(Z.ui),
|
||||
area(),
|
||||
'button',
|
||||
'btnOutline',
|
||||
]);
|
||||
|
||||
add([
|
||||
rect(SCALE*3.2, SCALE*0.7),
|
||||
pos(btnPos),
|
||||
origin('center'),
|
||||
color(rgb(80,80,80)),
|
||||
z(Z.ui),
|
||||
area(),
|
||||
'button',
|
||||
'clickable',
|
||||
{
|
||||
goTo: ['game', 'help'][i],
|
||||
}
|
||||
]);
|
||||
|
||||
add([
|
||||
rect(SCALE*3.0, SCALE*0.5),
|
||||
pos(btnPos),
|
||||
origin('center'),
|
||||
color(rgb(100,100,100)),
|
||||
z(Z.ui),
|
||||
'button',
|
||||
]);
|
||||
};
|
||||
|
||||
every('button', (r) => {
|
||||
r.radius = SCALE/5;
|
||||
});
|
||||
|
||||
onClick('clickable', (b) => {
|
||||
if (window.self == window.top) {
|
||||
fadeOut();
|
||||
setTimeout(() => {
|
||||
go(b.goTo);
|
||||
}, FADE_TIME);
|
||||
|
||||
} else {
|
||||
window.open('https://Ballistic-Chickens.mrvoo.repl.co', '_blank');
|
||||
};
|
||||
});
|
||||
|
||||
function newCloud(p) {
|
||||
add([
|
||||
sprite('cloud'),
|
||||
pos(p),
|
||||
scale(TILE*rand(2, 4)),
|
||||
move(180, SCALE),
|
||||
z(Z.bg),
|
||||
opacity(0.3),
|
||||
]);
|
||||
};
|
||||
|
||||
for (let i = 0; i < 6; i++) {
|
||||
newCloud(vec2(
|
||||
rand(0, width()),
|
||||
rand(0, height()),
|
||||
));
|
||||
};
|
||||
|
||||
onUpdate(() => {
|
||||
if (rand(0,100) < 6) {
|
||||
let speed = rand(15,22);
|
||||
let angle = randi(45, 80);
|
||||
add([
|
||||
sprite('chicken'),
|
||||
pos(rand(-2,9)*SCALE, -SCALE),
|
||||
origin('center'),
|
||||
move(angle, SCALE*speed),
|
||||
scale(TILE*1.5),
|
||||
rotate(angle),
|
||||
z(Z.bg +1),
|
||||
]);
|
||||
};
|
||||
|
||||
every('btnOutline', (o) => {
|
||||
o.color = o.isHovering() ? WHITE : BLACK;
|
||||
});
|
||||
|
||||
if (rand(0,400) < 2) {
|
||||
newCloud(vec2(
|
||||
width()+10,
|
||||
rand(-1,7)*SCALE
|
||||
));
|
||||
};
|
||||
|
||||
onKeyPress('a', () => {
|
||||
go('achievements');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
go('menu');
|
369
ballisticchickens/code/shop.js
Normal file
@ -0,0 +1,369 @@
|
||||
scene('retry', () => {
|
||||
add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
color(BLACK),
|
||||
])
|
||||
go('game');
|
||||
});
|
||||
|
||||
function truePrice(x) {
|
||||
let ox = OFFERS[x];
|
||||
return Math.floor(ox.cost * ox.expo ** STUFF.upgrades[x]);
|
||||
};
|
||||
|
||||
// Actual shop:
|
||||
|
||||
scene('shop', () => {
|
||||
const Z = {
|
||||
bg: 0,
|
||||
shop: 100,
|
||||
top: 200,
|
||||
black: 300,
|
||||
};
|
||||
|
||||
var selectedOffer = 0;
|
||||
|
||||
add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
z(Z.bg),
|
||||
opacity(1),
|
||||
color(rgb(110,65,30)),
|
||||
fixed(),
|
||||
]);
|
||||
|
||||
|
||||
const black = add([
|
||||
rect(width(), height()),
|
||||
pos(0,0),
|
||||
z(Z.black),
|
||||
opacity(1),
|
||||
color(BLACK),
|
||||
fixed(),
|
||||
]);
|
||||
|
||||
for (let f = 0; f < 20; f++) {
|
||||
setTimeout(() => {
|
||||
black.opacity -= 0.05;
|
||||
}, f*15);
|
||||
};
|
||||
|
||||
let fadingOut = false;
|
||||
function fadeOut() {
|
||||
if (!fadingOut) {
|
||||
fadingOut = true;
|
||||
for (let f = 0; f < 20; f++) {
|
||||
setTimeout(() => {
|
||||
black.opacity += 0.05;
|
||||
}, f * FADE_TIME / 20);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
let border = SCALE*0.05;
|
||||
let xOff = Math.sin( (Math.PI * i) /4 ) *border;
|
||||
let yOff = Math.cos( (Math.PI * i) /4 ) *border;
|
||||
if (i == 0) { xOff = 0; yOff = 0; };
|
||||
add([
|
||||
text('SHOP', {
|
||||
size: SCALE*1.3,
|
||||
align: 'center',
|
||||
font: 'rubik',
|
||||
}),
|
||||
pos(width()/2 +xOff, SCALE/3 +yOff),
|
||||
origin('top'),
|
||||
z(Z.top +(i == 0 ? 2:1)),
|
||||
color(i == 0 ? WHITE:BLACK),
|
||||
]);
|
||||
};
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
add([
|
||||
sprite('shopRoof', { frame:1 }),
|
||||
scale(2*TILE),
|
||||
pos(i*2*SCALE, SCALE*0.2),
|
||||
z(Z.top),
|
||||
opacity(0.2),
|
||||
]);
|
||||
add([
|
||||
sprite('shopRoof'),
|
||||
scale(2*TILE),
|
||||
pos(i*2*SCALE, 0),
|
||||
z(Z.top),
|
||||
]);
|
||||
};
|
||||
|
||||
add([
|
||||
sprite('shopNav'),
|
||||
scale(TILE * 2/3),
|
||||
pos(SCALE/10, SCALE/10),
|
||||
z(Z.top),
|
||||
area(),
|
||||
"menu",
|
||||
"navButton",
|
||||
]);
|
||||
add([
|
||||
sprite('shopNav', { frame:1 }),
|
||||
scale(TILE * 2/3),
|
||||
pos(SCALE*0.8, SCALE/10),
|
||||
z(Z.top),
|
||||
area(),
|
||||
"retry",
|
||||
"navButton",
|
||||
]);
|
||||
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
let border = SCALE*0.02;
|
||||
let xOff = Math.sin( (Math.PI * i) /4 ) *border;
|
||||
let yOff = Math.cos( (Math.PI * i) /4 ) *border;
|
||||
if (i == 0) { xOff = 0; yOff = 0; };
|
||||
add([
|
||||
text(`Balance: $${STUFF.money}`, {
|
||||
size: SCALE*0.3,
|
||||
font: 'ubuntu',
|
||||
}),
|
||||
pos(SCALE*0.8 +xOff, SCALE*2.6 +yOff),
|
||||
origin('botleft'),
|
||||
z(Z.top +(i == 0 ? 2:1)),
|
||||
color(i == 0 ? WHITE:BLACK),
|
||||
"balance",
|
||||
]);
|
||||
};
|
||||
|
||||
let yCenter = (height() - SCALE*2)/2 + SCALE*2.2;
|
||||
let xCount = 3;
|
||||
let yCount = 2;
|
||||
for (let y = 0; y < yCount; y++) {
|
||||
for (let x = 0; x < xCount; x++) {
|
||||
let index = y*3 + x;
|
||||
let itemPos = vec2(
|
||||
width()/2 + (-xCount/2 +x-0.88)*SCALE*1.5,
|
||||
yCenter + (-yCount/2 +y+0.5)*SCALE*1.5,
|
||||
);
|
||||
|
||||
add([
|
||||
sprite('box', { frame:1 }),
|
||||
scale(TILE*1.3),
|
||||
pos(itemPos),
|
||||
origin('center'),
|
||||
z(Z.shop),
|
||||
area(),
|
||||
"shopButton",
|
||||
{
|
||||
btn: index,
|
||||
}
|
||||
]);
|
||||
add([
|
||||
sprite('outline'),
|
||||
scale(TILE*1.3),
|
||||
pos(itemPos),
|
||||
origin('center'),
|
||||
z(Z.shop),
|
||||
area(),
|
||||
opacity(0),
|
||||
"outline"
|
||||
]);
|
||||
|
||||
add([
|
||||
sprite('upgrades', { frame: index }),
|
||||
scale(TILE*1.1),
|
||||
pos(itemPos),
|
||||
origin('center'),
|
||||
z(Z.shop),
|
||||
]);
|
||||
|
||||
add([
|
||||
text('0', {
|
||||
font: 'ubuntu',
|
||||
size: SCALE*0.25,
|
||||
align: 'right',
|
||||
}),
|
||||
pos(itemPos.add(SCALE*0.55, SCALE*0.55)),
|
||||
origin('botright'),
|
||||
z(Z.shop),
|
||||
"counter",
|
||||
{
|
||||
forOffer: index,
|
||||
}
|
||||
]);
|
||||
};
|
||||
};
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
add([
|
||||
sprite('shopGroove'),
|
||||
pos(SCALE*5, SCALE*1.5 + SCALE*i),
|
||||
scale(TILE*2),
|
||||
z(Z.bg),
|
||||
]);
|
||||
};
|
||||
|
||||
const buyBtn = add([
|
||||
rect(SCALE*3.2, SCALE*0.7),
|
||||
pos(SCALE*8.1, SCALE*5.3),
|
||||
origin('center'),
|
||||
color(rgb(80,80,80)),
|
||||
z(Z.shop),
|
||||
area(),
|
||||
'buyBtn',
|
||||
'buyRect',
|
||||
]);
|
||||
|
||||
const buyBtnInner = add([
|
||||
rect(SCALE*3.0, SCALE*0.5),
|
||||
pos(buyBtn.pos),
|
||||
origin('center'),
|
||||
color(rgb(100,100,100)),
|
||||
z(Z.shop),
|
||||
'buyRect',
|
||||
]);
|
||||
|
||||
add([
|
||||
rect(SCALE*3.25, SCALE*0.75),
|
||||
pos(buyBtn.pos),
|
||||
origin('center'),
|
||||
color(BLACK),
|
||||
z(Z.shop -1),
|
||||
area(),
|
||||
'buyRect',
|
||||
'btnOutline',
|
||||
]);
|
||||
|
||||
const price = add([
|
||||
text(' ', {
|
||||
align: 'center',
|
||||
width: SCALE*3,
|
||||
size: SCALE*0.4,
|
||||
font: 'manrope',
|
||||
letterSpacing: SCALE*0.03,
|
||||
}),
|
||||
pos(buyBtn.pos.add(0, SCALE*0.03)),
|
||||
origin('center'),
|
||||
z(Z.shop),
|
||||
]);
|
||||
|
||||
const selectedBox = add([
|
||||
sprite('box'),
|
||||
origin('center'),
|
||||
pos(SCALE*8.07, SCALE*3),
|
||||
scale(TILE*1.5),
|
||||
z(Z.shop),
|
||||
]);
|
||||
|
||||
const largeIcon = add([
|
||||
sprite('upgrades'),
|
||||
origin('center'),
|
||||
pos(SCALE*8.07, SCALE*3),
|
||||
scale(TILE*1.26),
|
||||
z(Z.shop),
|
||||
]);
|
||||
|
||||
add([
|
||||
rect(SCALE*3.5, SCALE*0.5),
|
||||
pos(largeIcon.pos.add(0, SCALE*0.7)),
|
||||
origin('center'),
|
||||
z(Z.shop),
|
||||
color(BLACK),
|
||||
opacity(0.5),
|
||||
'buyRect',
|
||||
]);
|
||||
|
||||
const label = add([
|
||||
text(' ', {
|
||||
size: SCALE*0.3,
|
||||
align: 'center',
|
||||
width: SCALE*3.5,
|
||||
font: 'rubik',
|
||||
}),
|
||||
pos(largeIcon.pos.add(0, SCALE*0.7)),
|
||||
origin('center'),
|
||||
z(Z.shop),
|
||||
]);
|
||||
|
||||
const description = add([
|
||||
text(' ', {
|
||||
size: SCALE*0.2,
|
||||
align: 'left',
|
||||
width: SCALE*3,
|
||||
font: 'ubuntu',
|
||||
}),
|
||||
pos(label.pos.add(0, SCALE*0.71)),
|
||||
origin('center'),
|
||||
z(Z.shop)
|
||||
]);
|
||||
|
||||
every('buyRect', (b) => {
|
||||
b.radius = SCALE/5;
|
||||
});
|
||||
|
||||
function updateShop() {
|
||||
let item = OFFERS[selectedOffer];
|
||||
|
||||
largeIcon.frame = selectedOffer;
|
||||
price.text = `$${shortNum(truePrice(selectedOffer))}`;
|
||||
label.text = item.name;
|
||||
description.text = item.desc;
|
||||
|
||||
every('balance', (b) => {
|
||||
b.text = `Balance: $${STUFF.money.toLocaleString('en-US')}`;
|
||||
});
|
||||
|
||||
every('shopButton', (b) => {
|
||||
let affordable = truePrice(b.btn) <= STUFF.money;
|
||||
let boxColor = affordable ? 0:1;
|
||||
b.frame = boxColor;
|
||||
|
||||
if (selectedOffer == b.btn) {
|
||||
selectedBox.frame = boxColor;
|
||||
let c1 = affordable ? 160 : 80;
|
||||
let c2 = affordable ? 200 : 100;
|
||||
buyBtn.color = affordable ?
|
||||
rgb(0,c1,0) : rgb(c1,c1,c1);
|
||||
buyBtnInner.color = affordable ?
|
||||
rgb(0,c2,0) : rgb(c2,c2,c2);
|
||||
};
|
||||
});
|
||||
|
||||
every('counter', (c) => {
|
||||
c.text = STUFF.upgrades[c.forOffer];
|
||||
});
|
||||
};
|
||||
updateShop();
|
||||
|
||||
onClick('shopButton', (b) => {
|
||||
selectedOffer = b.btn;
|
||||
updateShop();
|
||||
});
|
||||
|
||||
onClick('buyBtn', (b) => {
|
||||
if (truePrice(selectedOffer) <= STUFF.money) {
|
||||
STUFF.money -= truePrice(selectedOffer);
|
||||
STUFF.upgrades[selectedOffer]++;
|
||||
updateShop();
|
||||
};
|
||||
});
|
||||
|
||||
onClick('menu', (m) => {
|
||||
fadeOut();
|
||||
setTimeout(() => { go('menu'); }, FADE_TIME);
|
||||
});
|
||||
onClick('retry', (m) => {
|
||||
fadeOut();
|
||||
setTimeout(() => { go('retry'); }, FADE_TIME);
|
||||
});
|
||||
|
||||
onUpdate(() => {
|
||||
every('btnOutline', (o) => {
|
||||
o.color = o.isHovering() ? WHITE : BLACK;
|
||||
});
|
||||
every('outline', (o) => {
|
||||
o.opacity = o.isHovering() ? 1 : 0;
|
||||
});
|
||||
every('navButton', (o) => {
|
||||
o.scale = o.isHovering() ? vec2(TILE*0.73) : vec2(TILE*2/3);
|
||||
});
|
||||
});
|
||||
});
|
118
ballisticchickens/code/start.js
Normal file
@ -0,0 +1,118 @@
|
||||
let ratio = 0.6;
|
||||
|
||||
let ww = window.innerWidth;let wh = window.innerHeight;let kaboomDimensions = {};if (ww * ratio > wh) {kaboomDimensions = { w: wh / ratio,h: wh};} else {kaboomDimensions = {w: ww,h: ww * ratio};};
|
||||
|
||||
kaboom({
|
||||
background: [160,160,160],
|
||||
width: kaboomDimensions.w,
|
||||
height: kaboomDimensions.h,
|
||||
letterbox: true,
|
||||
inspectColor: [255,255,255],
|
||||
pixelDensity: 1/*Math.min(3, 1000 / kaboomDimensions.w)*/,
|
||||
crisp: true,
|
||||
});
|
||||
|
||||
function ls(a,b) {
|
||||
if (b == undefined) {
|
||||
loadSprite(a, `${a}.png`);
|
||||
} else {
|
||||
loadSprite(a, `${a}.png`, b);
|
||||
};
|
||||
};
|
||||
|
||||
const SCALE = width()/10;
|
||||
const SIZE = 400;
|
||||
const TILE = SCALE / SIZE;
|
||||
const FADE_TIME = 150;
|
||||
|
||||
loadFont('rubik', 'fonts/rubik.ttf');
|
||||
loadFont('ubuntu', 'fonts/ubuntu.ttf');
|
||||
loadFont('manrope', 'fonts/manrope.ttf');
|
||||
loadFont('burned', 'fonts/burned.ttf');
|
||||
|
||||
loadRoot('sprites/');
|
||||
|
||||
ls('cannon', { sliceX: 3 });
|
||||
ls('chicken', { sliceX: 2 });
|
||||
ls('ground');
|
||||
ls('collectables', { sliceX: 14 });
|
||||
ls('rocket', { sliceX: 2 });
|
||||
|
||||
loadSpriteAtlas('shopBuilder.png', {
|
||||
'shopRoof': {
|
||||
x: 0, y: 0,
|
||||
width: SIZE*2, height: SIZE,
|
||||
sliceX: 2,
|
||||
},
|
||||
'box': {
|
||||
x: SIZE*2, y: 0,
|
||||
width: SIZE*2, height: SIZE,
|
||||
sliceX: 2,
|
||||
},
|
||||
'shopNav': {
|
||||
x: SIZE*4, y: 0,
|
||||
width: SIZE*2, height: SIZE,
|
||||
sliceX: 2,
|
||||
},
|
||||
'shopGroove': {
|
||||
x: SIZE*6, y: 0,
|
||||
width: SIZE, height: SIZE,
|
||||
},
|
||||
'attention': {
|
||||
x: SIZE*7, y: 0,
|
||||
width: SIZE, height: SIZE,
|
||||
},
|
||||
});
|
||||
|
||||
ls('upgrades', { sliceX: 6 });
|
||||
ls('logo');
|
||||
|
||||
loadSpriteAtlas('gameExtras.png', {
|
||||
'trampoline': {
|
||||
x: 0, y: 0,
|
||||
width: SIZE, height: SIZE,
|
||||
},
|
||||
'cloud': {
|
||||
x: SIZE, y: 0,
|
||||
width: SIZE, height: SIZE,
|
||||
},
|
||||
'flora': {
|
||||
x: SIZE*2, y: 0,
|
||||
width: SIZE*3, height: SIZE,
|
||||
sliceX: 3,
|
||||
},
|
||||
'goldenEgg': {
|
||||
x: SIZE*5, y: 0,
|
||||
width: SIZE, height: SIZE,
|
||||
},
|
||||
'vaporCone': {
|
||||
x: SIZE*6, y: 0,
|
||||
width: SIZE, height: SIZE,
|
||||
},
|
||||
});
|
||||
|
||||
ls('outline');
|
||||
loadSpriteAtlas('update1dot1.png', {
|
||||
'banner': {
|
||||
x: 0, y: 0,
|
||||
width: SIZE*9, height: SIZE,
|
||||
sliceX: 9,
|
||||
},
|
||||
'achievements': {
|
||||
x: SIZE*9, y: 0,
|
||||
width: SIZE*6, height: SIZE,
|
||||
sliceX: 6,
|
||||
},
|
||||
'evilBird': {
|
||||
x: SIZE*15, y: 0,
|
||||
width: SIZE, height: SIZE,
|
||||
},
|
||||
'cork': {
|
||||
x: SIZE*16, y: 0,
|
||||
width: SIZE, height: SIZE,
|
||||
},
|
||||
'markerHouse': {
|
||||
x: SIZE*17, y: 0,
|
||||
width: SIZE, height: SIZE,
|
||||
},
|
||||
});
|
424
ballisticchickens/data.js
Normal file
@ -0,0 +1,424 @@
|
||||
// clouds: 1,000m to 7,500m
|
||||
// sky black: 30,000m
|
||||
// space: 100,000m
|
||||
|
||||
// 343m/s: sound barrier
|
||||
// 299 792 458 m/s: lightspeed hehehe
|
||||
|
||||
const ACHIEVEMENTS = {
|
||||
// distance
|
||||
'd1': {
|
||||
'icon': [0, -1],
|
||||
'description': 'Fly 500 meters in one round',
|
||||
},
|
||||
'd2': {
|
||||
'icon': [0, 0],
|
||||
'description': 'Fly 1,000 meters in one round',
|
||||
},
|
||||
'd3': {
|
||||
'icon': [0, 1],
|
||||
'description': 'Fly 5,000 meters in one round',
|
||||
},
|
||||
'd4': {
|
||||
'icon': [0, 2],
|
||||
'description': 'Fly 10,000 meters in one round',
|
||||
},
|
||||
'd5': {
|
||||
'icon': [0, 3],
|
||||
'description': 'Fly 50,000 meters in one round',
|
||||
},
|
||||
'd6': {
|
||||
'icon': [0, 4],
|
||||
'description': 'Fly 100,000 meters in one round',
|
||||
},
|
||||
'd7': {
|
||||
'icon': [0, 5],
|
||||
'description': 'Fly 500,000 meters in one round',
|
||||
},
|
||||
'd8': {
|
||||
'icon': [0, 6],
|
||||
'description': 'Fly 1 million meters in one round',
|
||||
},
|
||||
'd9': {
|
||||
'icon': [0, 7],
|
||||
'description': 'Fly 5 million meters in one round',
|
||||
},
|
||||
'd10': {
|
||||
'icon': [0, 8],
|
||||
'description': 'Fly 1 billion meters in one round',
|
||||
},
|
||||
// trampoline
|
||||
't1': {
|
||||
'icon': [1, -1],
|
||||
'description': 'Bounce off of a trampoline',
|
||||
},
|
||||
't2': {
|
||||
'icon': [1, 6],
|
||||
'description': 'Bounce off of 10 trampolines',
|
||||
},
|
||||
't3': {
|
||||
'icon': [1, 7],
|
||||
'description': 'Bounce off of 100 trampolines',
|
||||
},
|
||||
't4': {
|
||||
'icon': [1, 8],
|
||||
'description': 'Bounce off of 1,000 trampolines',
|
||||
},
|
||||
// upgrades
|
||||
'u1': {
|
||||
'icon': [2, -1],
|
||||
'description': 'Have one of each upgrade',
|
||||
},
|
||||
'u2': {
|
||||
'icon': [2, 0],
|
||||
'description': 'Have five of each upgrade',
|
||||
},
|
||||
'u3': {
|
||||
'icon': [2, 1],
|
||||
'description': 'Have 10 of each upgrade',
|
||||
},
|
||||
'u4': {
|
||||
'icon': [2, 2],
|
||||
'description': 'Have 15 of each upgrade',
|
||||
},
|
||||
'u5': {
|
||||
'icon': [2, 3],
|
||||
'description': 'Have 20 of each upgrade',
|
||||
},
|
||||
'u6': {
|
||||
'icon': [2, 4],
|
||||
'description': 'Have 25 of each upgrade',
|
||||
},
|
||||
'u7': {
|
||||
'icon': [2, 5],
|
||||
'description': 'Have 30 of each upgrade',
|
||||
},
|
||||
'u8': {
|
||||
'icon': [2, 6],
|
||||
'description': 'Have 35 of each upgrade',
|
||||
},
|
||||
'u9': {
|
||||
'icon': [2, 7],
|
||||
'description': 'Have 40 of each upgrade',
|
||||
},
|
||||
'u10': {
|
||||
'icon': [2, 8],
|
||||
'description': 'Have 50 of each upgrade',
|
||||
},
|
||||
// altitude
|
||||
'a1': {
|
||||
'icon': [3, -1],
|
||||
'description': 'Make it to space :O',
|
||||
},
|
||||
// velocity
|
||||
'v1': {
|
||||
'icon': [4, -1],
|
||||
'description': 'Fly at the speed of sound',
|
||||
},
|
||||
'v2': {
|
||||
'icon': [4, 0],
|
||||
'description': 'Fly at Mach 5',
|
||||
},
|
||||
'v3': {
|
||||
'icon': [4, 6],
|
||||
'description': 'Fly at Mach 10',
|
||||
},
|
||||
'v4': {
|
||||
'icon': [4, 7],
|
||||
'description': 'Fly at Mach 20',
|
||||
},
|
||||
'v5': {
|
||||
'icon': [4, 8],
|
||||
'description': 'Fly at Mach 50',
|
||||
},
|
||||
// birb
|
||||
'b1': {
|
||||
'icon': [5, -1],
|
||||
'description': 'Smack into an evil bird',
|
||||
},
|
||||
};
|
||||
|
||||
// 6 basic stars
|
||||
// 4 thicc stars
|
||||
// 4 special
|
||||
|
||||
const OFFERS = [
|
||||
{
|
||||
name: 'Launch Velocity',
|
||||
desc: 'Shove some more gunpowder into the cannon.',
|
||||
cost: 30,
|
||||
gain: 10,
|
||||
expo: 1.6,
|
||||
},
|
||||
{
|
||||
name: 'Aerodynamics',
|
||||
desc: 'Slice through the air as fast as... a chicken... through air...',
|
||||
cost: 100,
|
||||
gain: 3,
|
||||
expo: 1.8,
|
||||
},
|
||||
{
|
||||
name: 'Fuel Surplus',
|
||||
desc: 'Make more room in your fuel tank that doesn\'t really exist anyway.',
|
||||
cost: 200,
|
||||
gain: 50,
|
||||
expo: 1.5,
|
||||
},
|
||||
{
|
||||
name: 'Shock Absorber',
|
||||
desc: 'Lose less speed when you smack into the ground.',
|
||||
cost: 150,
|
||||
gain: 1,
|
||||
expo: 1.7,
|
||||
},
|
||||
{
|
||||
name: 'Lucky Not-Ducky',
|
||||
desc: 'Have an increased chance of trampolines appearing.',
|
||||
cost: 100,
|
||||
gain: 0.4,
|
||||
expo: 1.6,
|
||||
},
|
||||
{
|
||||
name: 'Rocket Science',
|
||||
desc: 'Get a better firework rocket to speed you up with less fuel.',
|
||||
cost: 150,
|
||||
gain: 0.1,
|
||||
expo: 1.7,
|
||||
},
|
||||
];
|
||||
|
||||
const STAR_TYPES = [
|
||||
{
|
||||
range: [800, 8000],
|
||||
count: 100,
|
||||
value: 0,
|
||||
frame: 'not a star lol',
|
||||
},
|
||||
{
|
||||
range: [3, 70],
|
||||
count: 5,
|
||||
value: 1,
|
||||
frame: 0,
|
||||
},
|
||||
{
|
||||
range: [70, 150],
|
||||
count: 5,
|
||||
value: 2,
|
||||
frame: 1,
|
||||
},
|
||||
{
|
||||
range: [150, 300],
|
||||
count: 10,
|
||||
value: 3,
|
||||
frame: 2,
|
||||
},
|
||||
{
|
||||
range: [300, 600],
|
||||
count: 20,
|
||||
value: 4,
|
||||
frame: 3,
|
||||
},
|
||||
{
|
||||
range: [600, 1000],
|
||||
count: 25,
|
||||
value: 5,
|
||||
frame: 4,
|
||||
},
|
||||
{
|
||||
range: [1000, 2000],
|
||||
count: 50,
|
||||
value: 7,
|
||||
frame: 5,
|
||||
},
|
||||
{
|
||||
range: [2000, 3000],
|
||||
count: 50,
|
||||
value: 10,
|
||||
frame: 0,
|
||||
},
|
||||
{
|
||||
range: [3000, 4000],
|
||||
count: 50,
|
||||
value: 15,
|
||||
frame: 1,
|
||||
},
|
||||
{
|
||||
range: [4000, 5000],
|
||||
count: 50,
|
||||
value: 20,
|
||||
frame: 2,
|
||||
},
|
||||
{
|
||||
range: [5000, 7500],
|
||||
count: 80,
|
||||
value: 25,
|
||||
frame: 3,
|
||||
},
|
||||
{
|
||||
range: [7500, 10000],
|
||||
count: 80,
|
||||
value: 30,
|
||||
frame: 4,
|
||||
},
|
||||
{
|
||||
range: [10000, 12500],
|
||||
count: 80,
|
||||
value: 35,
|
||||
frame: 5,
|
||||
},
|
||||
{
|
||||
range: [12500, 15000],
|
||||
count: 80,
|
||||
value: 40,
|
||||
frame: 0,
|
||||
},
|
||||
|
||||
{
|
||||
range: [15000, 20000],
|
||||
count: 160,
|
||||
value: 45,
|
||||
frame: 1,
|
||||
},
|
||||
{
|
||||
range: [20000, 25000],
|
||||
count: 160,
|
||||
value: 50,
|
||||
frame: 2,
|
||||
},
|
||||
|
||||
{
|
||||
range: [25000, 30000],
|
||||
count: 160,
|
||||
value: 55,
|
||||
frame: 3,
|
||||
},
|
||||
{
|
||||
range: [30000, 35000],
|
||||
count: 160,
|
||||
value: 60,
|
||||
frame: 4,
|
||||
},
|
||||
{
|
||||
range: [35000, 40000],
|
||||
count: 160,
|
||||
value: 65,
|
||||
frame: 5,
|
||||
},
|
||||
{
|
||||
range: [40000, 50000],
|
||||
count: 330,
|
||||
value: 70,
|
||||
frame: 0,
|
||||
},
|
||||
{
|
||||
range: [50000, 60000],
|
||||
count: 330,
|
||||
value: 75,
|
||||
frame: 1,
|
||||
},
|
||||
{
|
||||
range: [60000, 70000],
|
||||
count: 330,
|
||||
value: 80,
|
||||
frame: 2,
|
||||
},
|
||||
{
|
||||
range: [70000, 80000],
|
||||
count: 330,
|
||||
value: 85,
|
||||
frame: 3,
|
||||
},
|
||||
{
|
||||
range: [80000, 90000],
|
||||
count: 330,
|
||||
value: 90,
|
||||
frame: 4,
|
||||
},
|
||||
{
|
||||
range: [90000, 100000],
|
||||
count: 330,
|
||||
value: 95,
|
||||
frame: 5,
|
||||
},
|
||||
|
||||
// SPACE (100k)
|
||||
|
||||
{
|
||||
range: [100000, 150000],
|
||||
count: 1650,
|
||||
value: 100,
|
||||
frame: 6,
|
||||
},
|
||||
{
|
||||
range: [150000, 200000],
|
||||
count: 1650,
|
||||
value: 110,
|
||||
frame: 7,
|
||||
},
|
||||
{
|
||||
range: [200000, 250000],
|
||||
count: 1650,
|
||||
value: 120,
|
||||
frame: 8,
|
||||
},
|
||||
{
|
||||
range: [250000, 300000],
|
||||
count: 1650,
|
||||
value: 130,
|
||||
frame: 9,
|
||||
},
|
||||
|
||||
// FANCY SPACE
|
||||
|
||||
{
|
||||
range: [300000, 400000],
|
||||
count: 1650,
|
||||
value: 150,
|
||||
frame: 6,
|
||||
},
|
||||
{
|
||||
range: [300000, 400000],
|
||||
count: 1650,
|
||||
value: 300,
|
||||
frame: 10,
|
||||
},
|
||||
|
||||
{
|
||||
range: [400000, 600000],
|
||||
count: 3300,
|
||||
value: 200,
|
||||
frame: 7,
|
||||
},
|
||||
{
|
||||
range: [400000, 600000],
|
||||
count: 3300,
|
||||
value: 450,
|
||||
frame: 11,
|
||||
},
|
||||
|
||||
{
|
||||
range: [600000, 1000000],
|
||||
count: 6600,
|
||||
value: 300,
|
||||
frame: 8,
|
||||
},
|
||||
{
|
||||
range: [600000, 1000000],
|
||||
count: 6600,
|
||||
value: 700,
|
||||
frame: 12,
|
||||
},
|
||||
|
||||
{
|
||||
range: [1000000, 2000000],
|
||||
count: 13000,
|
||||
value: 500,
|
||||
frame: 9,
|
||||
},
|
||||
{
|
||||
range: [1000000, 2000000],
|
||||
count: 13000,
|
||||
value: 1200,
|
||||
frame: 13,
|
||||
},
|
||||
];
|
BIN
ballisticchickens/fonts/burned.ttf
Normal file
BIN
ballisticchickens/fonts/manrope.ttf
Normal file
BIN
ballisticchickens/fonts/rubik.ttf
Normal file
BIN
ballisticchickens/fonts/ubuntu.ttf
Normal file
33
ballisticchickens/index.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Ballistic Chickens</title>
|
||||
<script src="/js/all.js"></script>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<script src="https://unpkg.com/kaboom@2001.0.0-alpha.21/dist/kaboom.js"></script>
|
||||
<style>
|
||||
body {
|
||||
background: black;
|
||||
}
|
||||
canvas {
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src="data.js"></script>
|
||||
|
||||
<script src="code/start.js"></script>
|
||||
<script src="code/game.js"></script>
|
||||
<script src="code/shop.js"></script>
|
||||
<script src="code/menu.js"></script>
|
||||
<script src="code/achieve.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
BIN
ballisticchickens/logo.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
ballisticchickens/sprites/cannon.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
ballisticchickens/sprites/chicken.png
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
ballisticchickens/sprites/collectables.png
Normal file
After Width: | Height: | Size: 349 KiB |
BIN
ballisticchickens/sprites/gameExtras.png
Normal file
After Width: | Height: | Size: 257 KiB |
BIN
ballisticchickens/sprites/ground.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
ballisticchickens/sprites/logo.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
ballisticchickens/sprites/outline.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
ballisticchickens/sprites/rocket.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
ballisticchickens/sprites/shopBuilder.png
Normal file
After Width: | Height: | Size: 151 KiB |
BIN
ballisticchickens/sprites/trampoline.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
ballisticchickens/sprites/update1dot1.png
Normal file
After Width: | Height: | Size: 585 KiB |
BIN
ballisticchickens/sprites/upgrades.png
Normal file
After Width: | Height: | Size: 357 KiB |
25
ballisticchickens/stuff.md
Normal file
@ -0,0 +1,25 @@
|
||||
# To-Do
|
||||
|
||||
- [ ] eggs
|
||||
- [ ] another power up
|
||||
- [ ] obstacles?
|
||||
- [ ] achievements??
|
||||
|
||||
# Credits
|
||||
|
||||
Fonts are from [Google Fonts](https://fonts.google.com/)
|
||||
KaboomJS is used
|
||||
All code outside of the library is mine
|
||||
What else do I put here?
|
||||
|
||||
# Changelog
|
||||
|
||||
- **1.0.2** - December 14, 2022
|
||||
- Can now be played with the spacebar
|
||||
- Counters all show shortened numbers
|
||||
- **1.0.1** - December 13, 2022
|
||||
- Changed some star colors
|
||||
- Only works in a new tab
|
||||
- #1 on trending :)
|
||||
- **Release** - December 10, 2022
|
||||
- released lol
|
BIN
bobtherobber2/34d6aae0257d4e4c8068cbdfc11a8758-512x512.jpeg
Normal file
After Width: | Height: | Size: 342 KiB |
1
bobtherobber2/@source.txt
Normal file
@ -0,0 +1 @@
|
||||
https://html5.gamedistribution.com/rvvASMiM/34d6aae0257d4e4c8068cbdfc11a8758/
|
BIN
bobtherobber2/assets/atlases/Levels.png
Normal file
After Width: | Height: | Size: 4.8 MiB |
BIN
bobtherobber2/assets/atlases/Objects.png
Normal file
After Width: | Height: | Size: 7.6 MiB |
BIN
bobtherobber2/assets/atlases/PreloaderObjects.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
92
bobtherobber2/assets/css/app.css
Normal file
@ -0,0 +1,92 @@
|
||||
/*Stylesheet*/
|
||||
body, html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-text-size-adjust: none;
|
||||
-webkit-user-select: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Arial, Verdana, sans-serif;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: #ccc;
|
||||
background-color: #2e2e26;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#orientation {
|
||||
margin: 0 auto;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url(../images/rotate_landscape.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-color: rgb(0, 0, 0);
|
||||
background-size:25%;
|
||||
z-index: 999;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#loader {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
margin-top: 250px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#loader,
|
||||
#loader:after {
|
||||
border-radius: 50%;
|
||||
width: 10em;
|
||||
height: 10em;
|
||||
}
|
||||
#loader {
|
||||
margin: 60px auto;
|
||||
font-size: 10px;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-left: -5em;
|
||||
margin-top: -5em;
|
||||
text-indent: -9999em;
|
||||
border-top: 1.1em solid rgba(255, 255, 255, 0.2);
|
||||
border-right: 1.1em solid rgba(255, 255, 255, 0.2);
|
||||
border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);
|
||||
border-left: 1.1em solid #ffffff;
|
||||
-webkit-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
-webkit-animation: load8 1.1s infinite linear;
|
||||
animation: load8 1.1s infinite linear;
|
||||
}
|
||||
@-webkit-keyframes load8 {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes load8 {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
BIN
bobtherobber2/assets/images/rotate_landscape.png
Normal file
After Width: | Height: | Size: 6.6 KiB |