Skip to content

Instantly share code, notes, and snippets.

@metropolian
Created September 6, 2015 16:20
Show Gist options
  • Save metropolian/517734567de736038d09 to your computer and use it in GitHub Desktop.
Save metropolian/517734567de736038d09 to your computer and use it in GitHub Desktop.
Yoshi's Island
<div id="screen">
<span>
<img id="bkg0" src="map.gif" alt="">
<img id="bkg1" src="map.gif" alt="">
</span>
</div>
// ------ Yoshis Island ------
// Gerard Ferrandez - ge1doot - August 2005 (dhteumeuleu)
// GFX: from GBA Yoshi's Island TM (c)1995-2002 Nintendo
~ function() {
'use strict';
var map = [
// ---- map definition ----
{
src: "oam20.gif",
x: 0,
y: -256,
z: -30
}, // big mountain
{
src: "oam22.gif",
x: 0,
y: -172,
z: -30
}, // house big mountain
{
src: "oam24.gif",
x: 35,
y: -256,
z: -40
}, {
src: "oam24.gif",
x: 35,
y: -256,
z: 0
}, {
src: "oam24.gif",
x: -20,
y: -256,
z: -60
}, // mountain
{
src: "oam8.gif",
x: -40,
y: -256,
z: 0
}, {
src: "oam8.gif",
x: 20,
y: -256,
z: -70
}, // green talus
{
src: "oam3.gif",
x: -40,
y: -256,
z: -25
}, // red tower
{
src: "oam51.gif",
x: -40,
y: -256,
z: -25,
gr: 1
}, // ground
{
src: "oam5.gif",
x: -25,
y: -256,
z: -95
}, // volcano
{
src: "oam32.gif",
x: 60,
y: -256,
z: -60
}, {
src: "oam32.gif",
x: 50,
y: -256,
z: 40
}, {
src: "oam32.gif",
x: -40,
y: -256,
z: 40
}, // hill
{
src: "oam19.gif",
x: 80,
y: -256,
z: -70
}, {
src: "oam19.gif",
x: 80,
y: -256,
z: -40
}, {
src: "oam19.gif",
x: 60,
y: -256,
z: 60
}, {
src: "oam19.gif",
x: -60,
y: -256,
z: 50
}, {
src: "oam19.gif",
x: -60,
y: -256,
z: 20
}, // small hill
{
src: "oam52.gif",
x: 80,
y: -256,
z: -70,
gr: 1
}, {
src: "oam52.gif",
x: 60,
y: -256,
z: 60,
gr: 1
}, {
src: "oam52.gif",
x: -60,
y: -256,
z: 50,
gr: 1
}, // green ground
{
src: "oam14.gif",
x: 50,
y: -256,
z: -20
}, // grey donjon
{
src: "oam51.gif",
x: 50,
y: -256,
z: -20,
gr: 1
}, // ground
{
src: "oam14.gif",
x: 0,
y: -256,
z: 10
}, // grey donjon
{
src: "oam50.gif",
x: 0,
y: -256,
z: 10,
gr: 1
}, // castle water
{
src: "oam11.gif",
x: -12,
y: -256,
z: 10
}, {
src: "oam11.gif",
x: 12,
y: -256,
z: 10
}, {
src: "oam11.gif",
x: 0,
y: -256,
z: -2
}, {
src: "oam11.gif",
x: 0,
y: -256,
z: 22
}, // grey towers
{
src: "oam28.gif",
x: 60,
y: -256,
z: 15
}, // towers with red roof
{
src: "oam17.gif",
x: 50,
y: -256,
z: -80
}, // dolmen
{
src: "oam25.gif",
x: 65,
y: -256,
z: 30
}, {
src: "oam25.gif",
x: 85,
y: -256,
z: 30
}, {
src: "oam25.gif",
x: 70,
y: -256,
z: 10
}, {
src: "oam25.gif",
x: 70,
y: -256,
z: -20
}, // oranges
{
src: "oam10.gif",
x: 0,
y: -200,
z: -70
}, {
src: "oam10.gif",
x: 20,
y: -180,
z: -70
}, {
src: "oam10.gif",
x: 40,
y: -170,
z: -50
}, {
src: "oam10.gif",
x: 40,
y: -190,
z: -30
}, // cloud
{
src: "oam35.gif",
x: -50,
y: -160,
z: -10,
href: "http://codepen.io/ge1doot/"
}, // cloud castle
{
src: "oam2.gif",
x: -65,
y: -256,
z: -50
}, {
src: "oam2.gif",
x: -45,
y: -256,
z: -50
}, {
src: "oam2.gif",
x: -40,
y: -256,
z: -70
}, {
src: "oam2.gif",
x: -65,
y: -256,
z: -30
}, {
src: "oam2.gif",
x: -80,
y: -256,
z: -80
}, {
src: "oam2.gif",
x: -80,
y: -256,
z: -20
}, {
src: "oam2.gif",
x: -90,
y: -256,
z: 0
}, // fir
{
src: "oam1.gif",
x: -60,
y: -256,
z: -40
}, {
src: "oam1.gif",
x: -90,
y: -256,
z: -40
}, {
src: "oam1.gif",
x: -100,
y: -256,
z: -20
}, {
src: "oam1.gif",
x: -90,
y: -256,
z: -60
}, {
src: "oam1.gif",
x: -40,
y: -256,
z: -80
}, {
src: "oam1.gif",
x: -60,
y: -256,
z: -60
}, {
src: "oam1.gif",
x: -60,
y: -256,
z: -90
}, // small fir
{
src: "oam23.gif",
x: 60,
y: -256,
z: -40
}, {
src: "oam23.gif",
x: 60,
y: -256,
z: -30
}, {
src: "oam23.gif",
x: 60,
y: -256,
z: -90
}, {
src: "oam23.gif",
x: 70,
y: -256,
z: -90
}, {
src: "oam23.gif",
x: 50,
y: -256,
z: -95
}, {
src: "oam23.gif",
x: 90,
y: -256,
z: -40
}, // flower
{
src: "oam23.gif",
x: 95,
y: -256,
z: -50
}, {
src: "oam23.gif",
x: 95,
y: -256,
z: -30
}, {
src: "oam23.gif",
x: 80,
y: -256,
z: -20
}, {
src: "oam23.gif",
x: 80,
y: -256,
z: -10
}, {
src: "oam23.gif",
x: 100,
y: -256,
z: -10
}, {
src: "oam23.gif",
x: 100,
y: -256,
z: 0
}, // flower
{
src: "oam6.gif",
x: 30,
y: -256,
z: 30
}, {
src: "oam6.gif",
x: 20,
y: -256,
z: 40
}, {
src: "oam6.gif",
x: 20,
y: -256,
z: 60
}, {
src: "oam6.gif",
x: -20,
y: -256,
z: 30
}, {
src: "oam6.gif",
x: -20,
y: -256,
z: 50
}, {
src: "oam6.gif",
x: -30,
y: -256,
z: 60
}, {
src: "oam6.gif",
x: -10,
y: -256,
z: 90
}, // tree
{
src: "oam9.gif",
x: 30,
y: -256,
z: 45
}, {
src: "oam9.gif",
x: 35,
y: -256,
z: 60
}, {
src: "oam9.gif",
x: 45,
y: -256,
z: 70
}, {
src: "oam9.gif",
x: 50,
y: -256,
z: 90
}, {
src: "oam9.gif",
x: -20,
y: -256,
z: 90
}, {
src: "oam9.gif",
x: -15,
y: -256,
z: 70
}, {
src: "oam9.gif",
x: -10,
y: -256,
z: 35
}, // small tree
{
src: "oam16.gif",
x: 0,
y: -256,
z: 30
}, {
src: "oam16.gif",
x: 0,
y: -256,
z: 40
}, {
src: "oam16.gif",
x: 0,
y: -256,
z: 50
}, {
src: "oam16.gif",
x: 0,
y: -256,
z: 60
}, {
src: "oam16.gif",
x: 0,
y: -256,
z: 70
}, // plots
{
src: "oam4.gif",
x: -25,
y: -200,
z: -95,
mz: 10
}, {
src: "oam4.gif",
x: -25,
y: -220,
z: -95,
mz: 10
}, {
src: "oam4.gif",
x: -25,
y: -210,
z: -95,
mz: 10
}, // volcano smoke
{
src: "oam33.gif",
x: -10,
y: -172,
z: -23
}, {
src: "oam33.gif",
x: -15,
y: -169,
z: -21
}, {
src: "oam33.gif",
x: -20,
y: -166,
z: -19
}, {
src: "oam33.gif",
x: -25,
y: -163,
z: -17
}, {
src: "oam33.gif",
x: -30,
y: -160,
z: -15
}, // chain
{
src: "oam38.gif",
x: 20,
y: -200,
z: 40,
mz: 2
}, // seagull
{
src: "oam18.gif",
x: 20,
y: -256,
z: 40
} // Yoshi
];
// ----- private vars -----
var o = [],
ay = 2,
sin = Math.sin(ay * Math.PI / 180),
cos = Math.cos(ay * Math.PI / 180),
k = 0,
b1, b2;
// ----- prototype object -----
var CObj = function(p) {
this.loaded = false;
this.x = p.x;
this.y = p.y;
this.z = p.z;
this.gr = p.gr || false;
// ---- insert image -----
this.img = document.createElement("img");
this.img.src = p.src;
if (p.href) {
// ---- menu link -----
var a = document.createElement("a");
a.href = p.href;
a.appendChild(this.img);
scr.elem.appendChild(a);
this.img.style.left = '0';
this.css = a.style;
} else {
// ---- simple image -----
scr.elem.appendChild(this.img);
this.css = this.img.style;
}
// ---- vertical animation ----
this.mz = p.mz || false;
this.mzr = 0;
// ---- ground ----
this.gr = p.gr || false;
};
// ---- rotate function -----
CObj.prototype.rotate = function() {
if (this.mz) {
this.mzr += 0.5;
this.y += 0.5;
if (this.mzr > this.mz) {
this.y -= this.mzr;
this.mzr = 0;
}
}
var x1 = this.x * cos - this.z * sin;
this.z = this.z * cos + this.x * sin;
this.x = x1;
var r = scr.width / (scr.width + this.z);
if (this.loaded) {
this.css.transform = this.css.webkitTransform = 'matrix(1,0,0,1,' +
(scr.width * 0.5 + (2 * this.x * r) - (this.w0 * r) * 0.5) + ',' +
(-scr.height - (2 * this.y * r) - (this.h0 * r)) +
')';
this.css.zIndex = this.gr ? 0 : Math.round(100000 - this.z * 100);
} else {
// ----- image loaded -----
if (this.img.complete) {
this.loaded = true;
this.w0 = this.img.width;
this.h0 = this.img.height;
if (this.gr) this.h0 /= 1.5;
this.css.left = '0';
this.css.transform = this.css.webkitTransform = 'matrix(0,0,0,0,0,0)';
}
}
};
// ----- main loop -----
var run = function() {
// ---- RAF ----
requestAnimationFrame(run);
// ---- ay angle ----
ay = (scr.width * 0.5 - pointer.x) / 100;
ay = Math.min(1.2, Math.max(-1.2, ay));
sin = Math.sin(ay * Math.PI / 180);
cos = Math.cos(ay * Math.PI / 180);
// ---- background scrolling ----
b1.left = Math.round(k) + "px";
b2.left = Math.round(k + 512) + "px";
k -= ay * 2;
if (k > 0) k -= 512;
else if (k < -512) k += 512;
// ---- rotate elements ----
var i = 0,
p;
while (p = o[i++]) p.rotate();
};
// ---- screen ----
var scr = {
elem: document.getElementById("screen"),
resize: function() {
var o = this.elem;
this.width = o.offsetWidth;
this.height = o.offsetHeight;
for (this.left = 0, this.top = 0; o != null; o = o.offsetParent) {
this.left += o.offsetLeft;
this.top += o.offsetTop;
}
}
};
scr.resize();
// ---- pointer ----
var pointer = (function(canvas) {
var pointer = {
x: 0,
y: 0,
canvas: canvas,
isDown: false,
pointer: function(e) {
e.preventDefault();
var touchMode = e.targetTouches;
var pointer = touchMode ? touchMode[0] : e;
this.x = pointer.clientX - this.canvas.left;
this.y = pointer.clientY - this.canvas.top;
},
};
[
[window, 'mousemove,touchmove', function(e) {
this.pointer(e);
}],
[canvas.elem, 'mousedown,touchstart', function(e) {
this.pointer(e);
this.isDown = true;
}],
[window, 'mouseup,touchend,touchcancel', function(e) {
e.preventDefault();
this.isDown = false;
}]
].forEach(function(e) {
for (var i = 0, events = e[1].split(','); i < events.length; i++) {
e[0].addEventListener(events[i], e[2].bind(pointer), false);
}
}.bind(pointer));
return pointer;
}(scr));
scr.elem.onselectstart = function() {
return false;
}
b1 = document.getElementById("bkg0").style;
b2 = document.getElementById("bkg1").style;
// ---- add some grass ----
for (var i = 0; i < 40; i++) {
var r = Math.round(Math.random() * 180 - 90);
var a = Math.random() * 2 * Math.PI;
map.push({
src: "oam27.gif",
x: Math.round(r * Math.cos(a)),
y: -256,
z: Math.round(r * Math.sin(a))
});
}
// ---- create objects ----
for (var k = 0; k < map.length; k++) {
o.push(
new CObj(
map[k]
)
);
}
// ---- start engine ----
pointer.Xi = 50;
run();
}();
html {
overflow: hidden;
-ms-touch-action: none;
-ms-content-zooming: none;
}
body {
position: absolute;
background: #fff;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#screen {
position: absolute;
background: #000;
width: 512px;
height: 320px;
left: 50%;
top: 50%;
margin-left: -256px;
margin-top: -160px;
user-select: none;
outline: #eee solid 40px;
-webkit-transform: rotate(-3deg);
transform: rotate(-3deg);
}
#screen span {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#screen a,
img {
position: absolute;
border: none;
text-decoration: none;
left: -9999px;
}
*::selection {
background: transparent;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment