Created
August 13, 2019 23:30
-
-
Save eguneys/aad2ee1930ba782b187766c369bcf712 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var GAME = (function(){ | |
var states = {}; | |
assets = { | |
//font:{ | |
// string: "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_!@.'\"?/<()", | |
// bin: [ | |
// ["111111111011111111001111111111111111000111111111111000110000100011000101110111100111011110011111111110001100011000110001100011111100100011101111010010111110111111111011100111001110000000010011111010100000000110110110111000001000100001001000"], | |
// ["100011000110000100101000010000100001000100100000101001010000110111100110001100011000110001100000010010001100011000101010010100001001100100010000110010100001000000001100011000110001000000010010001111110000000010010011000100010001000010000100"], | |
// ["111111111010000100011110011100101111111100100000101110010000101011010110001100101000111110011100010010001100011010100100001000010000100000100011011111111101111000010011100111110001000000010010111010100000000100100100011000100010000010000100"], | |
// ["100011000110000100011000010000100011000100100100101001010000100011001110001111001001010001000010010010001010101010101010001000100000100001000000100010000011000100100100010000110001000000000010101111110000000000000000000001000001000010000100"], | |
// ["100011111001111111101111110000111111000111111111101000111111100011000101110100000111110001111100010001110001000111010001001001111101110111111111000010111100111000100011100111001110111110010010111010100010000000000000010010000000100001001000"] | |
// ], | |
// }, | |
letters: { | |
'-' : [ | |
[,,,,0], | |
[,,,,0], | |
[1,1,1,1,1], | |
[,,,,0], | |
[,,,,0] | |
], */ | |
} | |
}; | |
//--this gets wrapped in a closure, so no namespace object, compresses better. | |
var | |
C = document.getElementById('canvas'); | |
ctx = C.getContext('2d'), | |
renderTarget = 0x00000, | |
renderSource = 0x10000, | |
//Richard Fhager's DB32 Palette http://http://pixeljoint.com/forum/forum_posts.asp?TID=16247 | |
//ofcourse you can change this to whatever you like, up to 256 colors. | |
//one GOTCHA: colors are stored 0xAABBGGRR, so you'll have to flop the values from your typical hex colors. | |
colors = [0xff000000, 0xff342022, 0xff3c2845, 0xff313966, 0xff3b568f, 0xff2671df, 0xff66a0d9, 0xff9ac3ee, 0xff36f2fb, | |
0xff50e599, 0xff30be6a, 0xff6e9437, 0xff2f694b, 0xff244b52, 0xff393c32, 0xff743f3f, 0xff826030, 0xffe16e5b, | |
0xffff9b63, 0xffe4cd5f, 0xfffcdbcb, 0xffffffff, 0xffb7ad9b, 0xff877e84, 0xff6a6a69, 0xff525659, 0xff8a4276, | |
0xff3232ac, 0xff6357d9, 0xffba7bd7, 0xff4a978f, 0xff306f8a], | |
//default palette index | |
palDefault = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31], | |
//active palette index. maps to indices in colors[]. can alter this whenever for palette effects. | |
pal = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]; | |
ctx.imageSmoothingEnabled = false; | |
ctx.mozImageSmoothingEnabled = false; | |
C.width = C.height = 256; | |
var imageData = ctx.getImageData(0, 0, 256, 256), | |
buf = new ArrayBuffer(imageData.data.length), | |
buf8 = new Uint8Array(buf), | |
data = new Uint32Array(buf), | |
ram = new Uint8ClampedArray(0x80000); | |
//--------------graphics functions---------------- | |
function clear(color){ | |
ram.fill(color, renderTarget, renderTarget + 0x10000); | |
} | |
function pset(x, y, color) { //from colors array, 0-31 | |
x = x|0; y = y|0; | |
if (x > -1 && x < 256 && y > -1 && y < 256) { | |
ram[renderTarget + (y * 256 + x)] = color; | |
} | |
} | |
function line(x1, y1, x2, y2, color) { | |
x1 = x1|0; | |
x2 = x2|0; | |
y1 = y1|0; | |
y2 = y2|0; | |
var dy = (y2 - y1); | |
var dx = (x2 - x1); | |
var stepx, stepy; | |
if (dy < 0) { | |
dy = -dy; | |
stepy = -1; | |
} else { | |
stepy = 1; | |
} | |
if (dx < 0) { | |
dx = -dx; | |
stepx = -1; | |
} else { | |
stepx = 1; | |
} | |
dy <<= 1; // dy is now 2*dy | |
dx <<= 1; // dx is now 2*dx | |
pset(x1, y1, color); | |
if (dx > dy) { | |
var fraction = dy - (dx >> 1); // same as 2*dy - dx | |
while (x1 != x2) { | |
if (fraction >= 0) { | |
y1 += stepy; | |
fraction -= dx; // same as fraction -= 2*dx | |
} | |
x1 += stepx; | |
fraction += dy; // same as fraction -= 2*dy | |
pset(x1, y1, color); | |
} | |
; | |
} else { | |
fraction = dx - (dy >> 1); | |
while (y1 != y2) { | |
if (fraction >= 0) { | |
x1 += stepx; | |
fraction -= dy; | |
} | |
y1 += stepy; | |
fraction += dx; | |
pset(x1, y1, color); | |
} | |
} | |
} | |
function circle(xm, ym, r, color) { | |
var x = -r, y = 0, err = 2 - 2 * r; | |
/* II. Quadrant */ | |
do { | |
pset(xm - x, ym + y, color); | |
/* I. Quadrant */ | |
pset(xm - y, ym - x, color); | |
/* II. Quadrant */ | |
pset(xm + x, ym - y, color); | |
/* III. Quadrant */ | |
pset(xm + y, ym + x, color); | |
/* IV. Quadrant */ | |
r = err; | |
if (r <= y) err += ++y * 2 + 1; | |
/* e_xy+e_y < 0 */ | |
if (r > x || err > y) err += ++x * 2 + 1; | |
/* e_xy+e_x > 0 or no 2nd y-step */ | |
} while (x < 0); | |
} | |
function fillCircle(xm, ym, r, color) { | |
if(r < 0) return; | |
xm = xm|0; ym = ym|0, r = r|0; color = color|0; | |
var x = -r, y = 0, err = 2 - 2 * r; | |
/* II. Quadrant */ | |
do { | |
line(xm-x, ym-y, xm+x, ym-y, color); | |
line(xm-x, ym+y, xm+x, ym+y, color); | |
r = err; | |
if (r <= y) err += ++y * 2 + 1; | |
if (r > x || err > y) err += ++x * 2 + 1; | |
} while (x < 0); | |
} | |
function rect(x, y, w, h, color) { | |
x1 = x|0; | |
y1 = y|0; | |
x2 = (x+w)|0; | |
y2 = (y+h)|0; | |
line(x1,y1, x2, y1, color); | |
line(x2, y1, x2, y2, color); | |
line(x1, y2, x2, y2, color); | |
line(x1, y1, x1, y2, color); | |
} | |
function fr(x, y, w, h, color) { //draw a filled rectangle | |
x1 = x|0; | |
y1 = y|0; | |
x2 = (x+w)|0; | |
y2 = (y+h)|0; | |
var i = Math.abs(y2 - y1); | |
line(x1, y1, x2, y1, color); | |
if(i > 0){ | |
while (--i) { | |
line(x1, y1+i, x2, y1+i, color); | |
} | |
} | |
line(x1,y2, x2, y2, color); | |
} | |
function triangle(x1, y1, x2, y2, x3, y3, color) { | |
line(x1,y1, x2,y2, color); | |
line(x2,y2, x3,y3, color); | |
line(x3,y3, x1,y1, color); | |
} | |
function fillTriangle( x1, y1, x2, y2, x3, y3, color ) { | |
var canvasWidth = 256; | |
// http://devmaster.net/forums/topic/1145-advanced-rasterization/ | |
// 28.4 fixed-point coordinates | |
var x1 = Math.round( 16 * x1 ); | |
var x2 = Math.round( 16 * x2 ); | |
var x3 = Math.round( 16 * x3 ); | |
var y1 = Math.round( 16 * y1 ); | |
var y2 = Math.round( 16 * y2 ); | |
var y3 = Math.round( 16 * y3 ); | |
// Deltas | |
var dx12 = x1 - x2, dy12 = y2 - y1; | |
var dx23 = x2 - x3, dy23 = y3 - y2; | |
var dx31 = x3 - x1, dy31 = y1 - y3; | |
// Bounding rectangle | |
var minx = Math.max( ( Math.min( x1, x2, x3 ) + 0xf ) >> 4, 0 ); | |
var maxx = Math.min( ( Math.max( x1, x2, x3 ) + 0xf ) >> 4, 256 ); | |
var miny = Math.max( ( Math.min( y1, y2, y3 ) + 0xf ) >> 4, 0 ); | |
var maxy = Math.min( ( Math.max( y1, y2, y3 ) + 0xf ) >> 4, 256 ); | |
// Block size, standard 8x8 (must be power of two) | |
var q = 8; | |
// Start in corner of 8x8 block | |
minx &= ~(q - 1); | |
miny &= ~(q - 1); | |
// Constant part of half-edge functions | |
var c1 = -dy12 * x1 - dx12 * y1; | |
var c2 = -dy23 * x2 - dx23 * y2; | |
var c3 = -dy31 * x3 - dx31 * y3; | |
// Correct for fill convention | |
if ( dy12 > 0 || ( dy12 == 0 && dx12 > 0 ) ) c1 ++; | |
if ( dy23 > 0 || ( dy23 == 0 && dx23 > 0 ) ) c2 ++; | |
if ( dy31 > 0 || ( dy31 == 0 && dx31 > 0 ) ) c3 ++; | |
// Note this doesn't kill subpixel precision, but only because we test for >=0 (not >0). | |
// It's a bit subtle. :) | |
c1 = (c1 - 1) >> 4; | |
c2 = (c2 - 1) >> 4; | |
c3 = (c3 - 1) >> 4; | |
// Set up min/max corners | |
var qm1 = q - 1; // for convenience | |
var nmin1 = 0, nmax1 = 0; | |
var nmin2 = 0, nmax2 = 0; | |
var nmin3 = 0, nmax3 = 0; | |
if (dx12 >= 0) nmax1 -= qm1*dx12; else nmin1 -= qm1*dx12; | |
if (dy12 >= 0) nmax1 -= qm1*dy12; else nmin1 -= qm1*dy12; | |
if (dx23 >= 0) nmax2 -= qm1*dx23; else nmin2 -= qm1*dx23; | |
if (dy23 >= 0) nmax2 -= qm1*dy23; else nmin2 -= qm1*dy23; | |
if (dx31 >= 0) nmax3 -= qm1*dx31; else nmin3 -= qm1*dx31; | |
if (dy31 >= 0) nmax3 -= qm1*dy31; else nmin3 -= qm1*dy31; | |
// Loop through blocks | |
var linestep = (canvasWidth-q); | |
for ( var y0 = miny; y0 < maxy; y0 += q ) { | |
for ( var x0 = minx; x0 < maxx; x0 += q ) { | |
// Edge functions at top-left corner | |
var cy1 = c1 + dx12 * y0 + dy12 * x0; | |
var cy2 = c2 + dx23 * y0 + dy23 * x0; | |
var cy3 = c3 + dx31 * y0 + dy31 * x0; | |
// Skip block when at least one edge completely out | |
if (cy1 < nmax1 || cy2 < nmax2 || cy3 < nmax3) continue; | |
// Offset at top-left corner | |
var offset = (x0 + y0 * canvasWidth); | |
// Accept whole block when fully covered | |
if (cy1 >= nmin1 && cy2 >= nmin2 && cy3 >= nmin3) { | |
for ( var iy = 0; iy < q; iy ++ ) { | |
for ( var ix = 0; ix < q; ix ++, offset ++ ) { | |
ram[renderTarget + offset] = color; | |
} | |
offset += linestep; | |
} | |
} else { // Partially covered block | |
for ( var iy = 0; iy < q; iy ++ ) { | |
var cx1 = cy1; | |
var cx2 = cy2; | |
var cx3 = cy3; | |
for ( var ix = 0; ix < q; ix ++ ) { | |
if ( (cx1 | cx2 | cx3) >= 0 ) { | |
ram[renderTarget + offset] = color; | |
} | |
cx1 += dy12; | |
cx2 += dy23; | |
cx3 += dy31; | |
offset ++; | |
} | |
cy1 += dx12; | |
cy2 += dx23; | |
cy3 += dx31; | |
offset += linestep; | |
} | |
} | |
} | |
} | |
} | |
function spr(sx = 0, sy = 0, sw = 16, sh = 16, x=0, y=0, flipx = false, flipy = false){ | |
for(var i = 0; i < sh; i++){ | |
for(var j = 0; j < sw; j++){ | |
if(y+i < 255 && x+j < 255 && y+i > -1 && x+j > -1){ | |
if(flipx & flipy){ | |
if(ram[(renderSource + ( ( sy + (sh-i) )*256+sx+(sw-j)))] > 0) { | |
ram[ (renderTarget + ((y+i)*256+x+j)) ] = pal[ ram[(renderSource + ((sy+(sh-i))*256+sx+(sw-j)))] ]; | |
} | |
} | |
else if(flipy && !flipx){ | |
if(ram[(renderSource + ( ( sy + (sh-i) )*256+sx+j))] > 0) { | |
ram[ (renderTarget + ((y+i)*256+x+j)) ] = ram[(renderSource + ((sy+(sh-i))*256+sx+j))]; | |
} | |
} | |
else if(flipx && !flipy){ | |
if(ram[(renderSource + ((sy+i)*256+sx+(sw-j)))] > 0) { | |
ram[ (renderTarget + ((y+i)*256+x+j)) ] = ram[(renderSource + ((sy+i)*256+sx+(sw-j)))]; | |
} | |
} | |
else if(!flipx && !flipy){ | |
if(ram[(renderSource + ((sy+i)*256+sx+j))] > 0) { | |
ram[ (renderTarget + ((y+i)*256+x+j)) ] = pal[ ram[(renderSource + ((sy+i)*256+sx+j))] ]; | |
} | |
} | |
} | |
} | |
} | |
} | |
function sspr(sx = 0, sy = 0, sw = 16, sh = 16, x=0, y=0, dw=16, dh=16, flipx = false, flipy = false){ | |
var xratio = sw / dw; | |
var yratio = sh / dh; | |
for(var i = 0; i < dh; i++){ | |
for(var j = 0; j < dw; j++){ | |
px = (j*xratio)|0; | |
py = (i*yratio)|0; | |
if(y+i < 255 && x+j < 255 && y+i > -1 && x+j > -1) { | |
if (ram[(renderSource + ((sy + py) * 256 + sx + px))] > 0) { | |
ram[(renderTarget + ((y + i) * 256 + x + j))] = ram[(renderSource + ((sy + py) * 256 + sx + px))] | |
} | |
} | |
} | |
} | |
} | |
function rspr( sx, sy, sw, sh, destCenterX, destCenterY, scale, angle ){ | |
angle = angle * 0.0174533 //convert to radians in place | |
var sourceCenterX = sx + sw / 2; | |
var sourceCenterY = sy + sh / 2; | |
var destWidth = sw * scale; | |
var destHeight = sh * scale; | |
var halfWidth = (destWidth / 2 * 1.41421356237)|0 + 5; //area will always be square, hypotenuse trick | |
var halfHeight = (destHeight / 2 * 1.41421356237)|0 + 5; | |
var startX = -halfWidth; | |
var endX = halfWidth; | |
var startY = -halfHeight; | |
var endY = halfHeight; | |
var scaleFactor = 1.0 / scale; | |
var cos = Math.cos(-angle) * scaleFactor; | |
var sin = Math.sin(-angle) * scaleFactor; | |
for(let y = startY; y < endY; y++){ | |
for(let x = startX; x < endX; x++){ | |
let u = sourceCenterX + Math.round(cos * x + sin * y); | |
let v = sourceCenterY + Math.round(-sin * x + cos * y); | |
let drawX = (x + destCenterX)|0; | |
let drawY = (y + destCenterY)|0; | |
if(u >= 0 && v >= 0 && u < sw && v < sh){ | |
if( ram[ (renderSource + (v * 256 + u)) ] > 0) { | |
ram[(renderTarget + (drawY * 256 + drawX)) ] = ram[(renderSource + ( v * 256 + u )) ] | |
} | |
} | |
} //end x loop | |
} //end outer y loop | |
} | |
function checker(w, h, nRow, nCol, color) { | |
//var w = 256; | |
//var h = 256; | |
var x = 0; | |
var y = 0; | |
nRow = nRow || 8; // default number of rows | |
nCol = nCol || 8; // default number of columns | |
w /= nCol; // width of a block | |
h /= nRow; // height of a block | |
for (var i = 0; i < nRow; ++i) { | |
for (var j = 0, col = nCol / 2; j < col; ++j) { | |
x = 2 * j * w + (i % 2 ? 0 : w); | |
y = i * h; | |
fr(x, y, w-1, h-1, color); | |
} | |
} | |
} | |
// util: { | |
// | |
// toPolarScreen(p){ | |
// let degrees = (360/256) * p.x * 0.0174533; | |
// let radius = p.y / 2; | |
// return util.polarToPoint(degrees, radius); | |
// }, | |
// | |
// norm(value, min, max){ | |
// return (value - min) / (max - min); | |
// }, | |
// | |
// dist(x0, y0, x1, y1) { | |
// if(arguments.length === 2) { | |
// return this.dist(x0.x, x0.y, y0.x, y0.y); | |
// } | |
// var dx = x1 - x0, | |
// dy = y1 - y0; | |
// return Math.sqrt(dx * dx + dy * dy); | |
// }, | |
// | |
// | |
// polarToPoint(angle, radius) { | |
// return { | |
// x: Math.cos(angle) * radius, | |
// y: Math.sin(angle) * radius | |
// }; | |
// }, | |
// | |
// pointToPolar(p) { | |
// return { | |
// angle: Math.atan2(p.y, p.x), | |
// radius: this.magnitude(p) | |
// }; | |
// }, | |
// | |
// magnitude(p) { | |
// return this.dist(0, 0, p.x, p.y); | |
// }, | |
// | |
// scale(p) { | |
// | |
// } | |
// | |
// | |
// }, | |
function render() { | |
var i = 0x10000; // display is first 0x10000 bytes of ram | |
while (i--) { | |
/* | |
data is 32bit view of final screen buffer | |
for each pixel on screen, we look up it's color and assign it | |
*/ | |
data[i] = colors[pal[ram[i]]]; | |
} | |
imageData.data.set(buf8); | |
ctx.putImageData(imageData, 0, 0); | |
} | |
function Particle() { | |
this.inUse = false; | |
this.init = function(){ | |
this.x = -500; | |
this.y = -500; | |
this.dead = true; | |
this.xvel = 0; | |
this.yvel = 1; | |
this.life = 1; | |
} | |
Particle.prototype.spawn = function(opt) { | |
this.x = opt.x; | |
this.y = opt.y; | |
this.xvel = opt.xvel; | |
this.yvel = opt.yvel; | |
this.inUse = true; | |
this.life = opt.life || 1; | |
this.remaining = opt.life || 1; | |
this.radius = opt.radius || 1; | |
this.color = opt.color || 21; | |
this.dead = false; | |
} | |
Particle.prototype.use = function(dt){ | |
if(this.dead) { | |
return true; | |
} | |
else { | |
this.remaining -= dt; | |
this.x += dt * this.xvel; | |
this.y += dt * this.yvel; | |
this.draw(); | |
//console.log('bullet used/updated'); | |
if(this.remaining <= 0) { | |
this.dead = true; | |
return true; | |
} | |
if(this.y < 0){ | |
this.dead = true; | |
} | |
} | |
return false; | |
} | |
Particle.prototype.clear = function(){ | |
this.x = -500; | |
this.y = -500; | |
this.dead = true; | |
this.xvel = 0; | |
this.yvel = 0; | |
this.life = 1; | |
this.inUse = false; | |
} | |
Particle.prototype.draw = function(){ | |
circle(this.x, this.y, 0|Math.random()*4, 21); | |
} | |
} | |
Key = { | |
_pressed: {}, | |
_released: {}, | |
LEFT: 37, | |
UP: 38, | |
RIGHT: 39, | |
DOWN: 40, | |
SPACE: 32, | |
a: 65, | |
w: 87, | |
s: 83, | |
d: 68, | |
z: 90, | |
x: 88, | |
f: 70, | |
p: 80, | |
r: 82, | |
isDown(keyCode) { | |
return this._pressed[keyCode]; | |
}, | |
justReleased(keyCode) { | |
return this._released[keyCode]; | |
}, | |
onKeydown(event) { | |
this._pressed[event.keyCode] = true; | |
}, | |
onKeyup(event) { | |
this._released[event.keyCode] = true; | |
delete this._pressed[event.keyCode]; | |
}, | |
update() { | |
this._released = {}; | |
} | |
}; | |
Txt = { | |
textLine(opt) { | |
var textLength = opt.text.length, | |
size = 5; | |
for (var i = 0; i < textLength; i++) { | |
var letter = assets.letters[( opt.text.charAt(i) )] || assets.letters['unknown']; | |
for (var y = 0; y < size; y++) { | |
//var g = (Math.random() > opt.glitchChance) * opt.glitchFactor; | |
for (var x = 0; x < size; x++) { | |
if (letter[y][x] === 1) { | |
//var gx = (Math.random() < gl.xch || 0) * (Math.random()-.5) * gl.xamt || 0; | |
//var gy = (Math.random() < gl.ych || 0) * (Math.random()-.5) * gl.yamt || 0; | |
if(opt.scale === 1){ | |
pset( | |
opt.x + ( x * opt.scale ) + ( ( size * opt.scale ) + opt.hspacing ) * i, | |
opt.y + (y * opt.scale), | |
opt.color | |
); | |
} | |
else { | |
fr( | |
opt.x + ( x * opt.scale ) + ( ( size * opt.scale ) + opt.hspacing ) * i, | |
opt.y + (y * opt.scale), | |
opt.scale, | |
opt.scale, | |
opt.color); | |
} | |
//console.log(opt.color); | |
} | |
} | |
} | |
} | |
}, | |
text(opt) { | |
var size = 5, | |
letterSize = size * opt.scale, | |
lines = opt.text.split('\n'), | |
linesCopy = lines.slice(0), | |
lineCount = lines.length, | |
longestLine = linesCopy.sort(function (a, b) { | |
return b.length - a.length; | |
})[0], | |
textWidth = ( longestLine.length * letterSize ) + ( ( longestLine.length - 1 ) * opt.hspacing ), | |
textHeight = ( lineCount * letterSize ) + ( ( lineCount - 1 ) * opt.vspacing ); | |
if(!opt.halign)opt.halign = 'left'; | |
if(!opt.valign)opt.valign = 'bottom'; | |
var sx = opt.x, | |
sy = opt.y, | |
ex = opt.x + textWidth, | |
ey = opt.y + textHeight; | |
if (opt.halign == 'center') { | |
sx = opt.x - textWidth / 2; | |
ex = opt.x + textWidth / 2; | |
} else if (opt.halign == 'right') { | |
sx = opt.x - textWidth; | |
ex = opt.x; | |
} | |
if (opt.valign == 'center') { | |
sy = opt.y - textHeight / 2; | |
ey = opt.y + textHeight / 2; | |
} else if (opt.valign == 'bottom') { | |
sy = opt.y - textHeight; | |
ey = opt.y; | |
} | |
var cx = sx + textWidth / 2, | |
cy = sy + textHeight / 2; | |
if (opt.render) { | |
for (var i = 0; i < lineCount; i++) { | |
var line = lines[i], | |
lineWidth = ( line.length * letterSize ) + ( ( line.length - 1 ) * opt.hspacing ), | |
x = opt.x, | |
y = opt.y + ( letterSize + opt.vspacing ) * i; | |
if (opt.halign == 'center') { | |
x = opt.x - lineWidth / 2; | |
} else if (opt.halign == 'right') { | |
x = opt.x - lineWidth; | |
} | |
if (opt.valign == 'center') { | |
y = y - textHeight / 2; | |
} else if (opt.valign == 'bottom') { | |
y = y - textHeight; | |
} | |
if (opt.snap) { | |
x = Math.floor(x); | |
y = Math.floor(y); | |
} | |
this.textLine({ | |
ctx: opt.ctx, | |
x: x, | |
y: y, | |
text: line, | |
hspacing: opt.hspacing || 0, | |
scale: opt.scale || 1, | |
color: opt.color | |
}); | |
} | |
} | |
return { | |
sx: sx, | |
sy: sy, | |
cx: cx, | |
cy: cy, | |
ex: ex, | |
ey: ey, | |
width: textWidth, | |
height: textHeight | |
} | |
} | |
}; | |
states.gameover = { | |
step: function(dt) { | |
if(Key.isDown(Key.r)){ | |
state = 'menu'; | |
} | |
}, | |
render: function(dt) { | |
fr(0,0,256,256, 0); | |
fr(0,0,64,64,2); | |
Txt.text({ | |
x: 128, | |
y: 40 + Math.sin(t*2.5)*15, | |
text: 'GAME\nOVER', | |
hspacing: 8 + Math.cos(t*2.9)*4, | |
vspacing: 15 + Math.sin(t*3.5)*5, | |
halign: 'center', | |
valign: 'top', | |
scale: 10, | |
snap: 1, | |
render: 1, | |
color: 21, | |
}); | |
}, | |
}; | |
states.menu = { | |
step: function(dt) { | |
//game update | |
if(Key.isDown(Key.p)){ | |
state = 'game'; | |
} | |
}, | |
render: function(dt) { | |
fr(0,0,256,256, 0); | |
fr(0,0,64,64,2); | |
Txt.text({ | |
x: 128, | |
y: 40 + Math.sin(t*2.5)*15, | |
text: 'MENU', | |
hspacing: 8 + Math.cos(t*2.9)*4, | |
vspacing: 15 + Math.sin(t*3.5)*5, | |
halign: 'center', | |
valign: 'top', | |
scale: 10, | |
snap: 1, | |
render: 1, | |
color: 21, | |
}); | |
//draw stuff here. | |
}, | |
}; | |
states.game = { | |
step(dt) { | |
player.update(dt); | |
//----hacky sound test | |
if(Key.justReleased(Key.z)){ | |
songTrigger = true | |
} | |
if(songTrigger){ | |
// playSound(sounds.song, 1, 1, 0); | |
songTrigger = false; | |
incrementState(); | |
} | |
//---end hacky sound test | |
bulletPool.use(); | |
Key.update(); | |
}, | |
render(dt) { | |
renderTarget = 0x00000; | |
switch(demostate){ | |
case 1: | |
clear(0); | |
let r = 40; | |
for(x=0; x < 256; x+=r){ | |
for( y=0; y < 256; y+=r){ | |
let A = x-128+Math.sin(t)*r; | |
let B = y-128+Math.cos(t)*r; | |
let s = Math.sqrt(A*A+B*B); | |
circle(x,y, s-8, 21); | |
} | |
} | |
renderInstructions(); | |
break; | |
case 2: | |
clear(0); | |
for(let a = 0; a < 2 * Math.PI; a+= 0.7){ | |
for(let r = 20; r < 200; r += 9){ | |
let v = a + .4 * Math.sin(a*8-r/20+t); | |
fillCircle((128+r*Math.cos(v)), 128+r*Math.sin(v), (10-r/12)|0, 10+(r/9%32)|0 ); | |
} | |
} | |
renderInstructions(); | |
break; | |
case 0: | |
//clear(0); | |
for(let u = 0; u < 1; u+=.001){ | |
let x = Math.floor(128+128*Math.cos(3*u+t)); | |
let y = Math.floor(128+128*Math.sin(5*u+t)); | |
y = x^y; | |
pset(x,y,u*32); | |
} | |
renderInstructions(); | |
break; | |
case 3: | |
clear(1); | |
renderColorNumbers(); | |
renderDrawingAPI(); | |
renderInstructions(); | |
break; | |
case 4: | |
clear(1); | |
let s = 128; | |
let i = t/3; | |
for(let y = -s; y < s; y += 3 ){ | |
for(let x = -s; x < s; x += 2 ){ | |
pset(s+x+64*Math.cos( (y/s+i)*5 )+y, s+y+64*Math.sin( (x/s+i)*5 )+x, x/8%32) | |
} | |
} | |
renderInstructions(); | |
break; | |
case 5: | |
clear(0); | |
for(let r = 0; r < 190; r+= 6){ | |
for(let a = 0; a < 2*Math.PI; a += 1/r*8){ | |
let x = r*Math.cos(a+t); | |
let y = r*Math.sin(a+t); | |
circle(x+128, y+128, 3+3*Math.cos(t*r/8+a*3), r/8%32) | |
} | |
} | |
renderInstructions(); | |
break; | |
default: | |
clear(0); | |
renderInstructions(); | |
break; | |
} | |
}, | |
}; | |
function incrementState(){ | |
demostate += 1; | |
if(demostate > 6){ | |
demostate = 0; | |
} | |
} | |
function renderColorNumbers(){ | |
for(var i = 0; i < 32; i++){ | |
Txt.text({ | |
x: i < 16 ? ( 3+16*i ) : ( 3 + 16* (i-16) ) , | |
y: i < 16 ? 8 : 8 + 16, | |
text: i.toString(), | |
scale: 1, | |
snap: 1, | |
hspacing: 1, | |
vspacing: 2, | |
halign: 'left', | |
valign: 'bottom', | |
render: 1, | |
color: i, | |
}) | |
} | |
} | |
function renderDrawingAPI(){ | |
pset(16*2, 16*5, 21); | |
line(16*4, 16*5, 16*5, 16*7, 21); | |
rect(16*6, 16*5, 16, 32, 21); | |
circle(16*8, 16*6, 16, 21); | |
} | |
function renderInstructions(){ | |
fr(5,243,256,6,0); | |
Txt.text({ | |
x: 5, | |
y: 249, | |
text: "THINGY "+ demostate + ": PRESS Z TO SEE NEXT THINGY", | |
scale: 1, | |
snap: 1, | |
hspacing: 1, | |
vspacing: 2, | |
halign: 'left', | |
valign: 'bottom', | |
render: 1, | |
color: 21, | |
}) | |
} | |
player = { | |
// x: 0, | |
// y: 0, | |
// radius: 12, | |
// xvel: 0, | |
// yvel: 0, | |
// speed: 6, | |
// drag: .97, | |
bullet: { | |
x: 0, y:0, xvel: 0, yvel: 0 | |
}, | |
init (){ | |
this.x = 64; | |
this.y = 230; | |
this.radius = 12; | |
this.xvel = 0; | |
this.yvel = 0; | |
this.xspeed = 400; | |
this.yspeed = 400; | |
this.drag = .6; | |
}, | |
update (dt) { | |
this.bullet.x = player.x; | |
this.bullet.y = player.y; | |
this.xvel *= player.drag; | |
this.yvel *= player.drag; | |
let xIntegrate = dt * player.xvel; | |
let yIntegrate = dt * player.yvel; | |
player.x += xIntegrate; | |
player.y += yIntegrate; | |
//player movement | |
if (Key.isDown(Key.d) || Key.isDown(Key.RIGHT)) { | |
player.xvel = player.xspeed; | |
} | |
if (Key.isDown(Key.a) || Key.isDown(Key.LEFT)){ | |
player.xvel = - player.xspeed; | |
} | |
if(Key.isDown(Key.w) || Key.isDown(Key.UP)){ | |
player.yvel = -player.yspeed; | |
} | |
if(Key.isDown(Key.s) || Key.isDown(Key.DOWN)) { | |
player.yvel = player.yspeed; | |
} | |
if(Key.isDown(Key.SPACE || Key.isDown(Key.z))){ | |
//player.bullet.xvel = E.player.xvel; | |
player.bullet.yvel = -350; | |
bulletPool.get(player.bullet); | |
} | |
//world wrap for player | |
if(player.x > 256){ | |
player.x = 0; | |
} | |
if(player.x < 0){ | |
player.x = 256; | |
} | |
if(player.y > 256){ | |
player.y = 0; | |
} | |
if(player.y < 0){ | |
state = 'gameover'; | |
player.y = 256; | |
} | |
//end world wrap for player | |
}, | |
draw (dt) { | |
// let degrees = (360/256) * E.player.x * 0.0174533; | |
// let radius = (E.player.y / 2); | |
// let playerDrawPoint = E.util.toPolarScreen({x:E.player.x, y:E.player.y}); | |
// | |
// let distFromCenter = E.util.dist(playerDrawPoint.x+128, playerDrawPoint.y+128, 128,128); | |
// | |
// let playerSizeFactor = E.util.norm(distFromCenter, 0, 128); | |
//E.renderTarget = E.screen; | |
//E.gfx.fillCircle(playerDrawPoint.x+128, playerDrawPoint.y+128, E.player.radius * playerSizeFactor, 21); | |
fillCircle(this.x, this.y, this.radius, 21); | |
}, | |
} | |
init = function(){ | |
last = 0; | |
dt = 0; | |
now = 0; | |
t = 0; | |
moveX = 0; | |
speedFactor = .6; | |
songTrigger = false; | |
state = 'game'; | |
demostate = 0, | |
bulletPool = new Pool(100, Particle); | |
sounds = {}; | |
//stats = new Stats(); | |
//document.body.appendChild( stats.dom ); | |
starColors=[15,16,17,18,19,20,21]; | |
bulletPool.init(); | |
player.init(); | |
soundInit(); | |
eventInit(); | |
//init vid capture | |
//capturer = new CCapture( {format: 'gif', workersPath: ''}); | |
//capturer.start(); | |
//start the game loop | |
loop(); | |
}, | |
stopCapture = (e) => { | |
//capturer.stop(); | |
//capturer.save(); | |
} | |
loop = () => { | |
// stats.begin(); | |
//game timer | |
let now = new Date().getTime(); | |
dt = Math.min(1, (now - last) / 1000); | |
t += dt; | |
//draw current state to buffer | |
states[state].render(); | |
//update | |
states[state].step(dt); | |
last = now; | |
//draw buffer to screen | |
render(); | |
//GIF capture | |
//capturer.capture(C); | |
//stats.end(); | |
requestAnimationFrame(loop); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment