Skip to content

Instantly share code, notes, and snippets.

@eguneys
Created August 14, 2019 02:40
Show Gist options
  • Save eguneys/fe825bef136568bb292689bd21b6c114 to your computer and use it in GitHub Desktop.
Save eguneys/fe825bef136568bb292689bd21b6c114 to your computer and use it in GitHub Desktop.
var GAME = (function(){
var states = {};
assets = {
// font:{
// string: "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_!@.'\"?/<()",
//
// // bin: '~cQz??I#_CH?|Ba<?FcdO~Rz90B?uFs,q:bwQKH 2?h} /A`}yHc .FT$1VW"Q'+
// // 'F!D>#g"xtR|!?Ayx= _"t.Eg"x.:bpH!xo-j}/TC mQ@" BB',
// // bin: [
// // ["111111111011111111001111111111111111000111111111111000110000100011000101110111100111011110011111111110001100011000110001100011111100100011101111010010111110111111111011100111001110000000010011111010100000000110110110111000001000100001001000"],
// // ["100011000110000100101000010000100001000100100000101001010000110111100110001100011000110001100000010010001100011000101010010100001001100100010000110010100001000000001100011000110001000000010010001111110000000010010011000100010001000010000100"],
// // ["111111111010000100011110011100101111111100100000101110010000101011010110001100101000111110011100010010001100011010100100001000010000100000100011011111111101111000010011100111110001000000010010111010100000000100100100011000100010000010000100"],
// // ["100011000110000100011000010000100011000100100100101001010000100011001110001111001001010001000010010010001010101010101010001000100000100001000000100010000011000100100100010000110001000000000010101111110000000000000000000001000001000010000100"],
// // ["100011111001111111101111110000111111000111111111101000111111100011000101110100000111110001111100010001110001000111010001001001111101110111111111000010111100111000100011100111001110111110010010111010100010000000000000010010000000100001001000"]
// // ],
// // bigString: "11111100011111110001100011111010001111101000111110111111000010000100000111111100100101000110001111101111110000111001000011111111111000"+
// // "0111001000010000111111000010111100011111110001100011111110001100011111100100001000010011111111110001000010100101111010001100101110010010100011000"+
// // "0100001000010000111111000111011101011000110001100011100110101100111000101110100011000110001011101111010001100101110010000011101000110001100100111"+
// // "1111101000111110100011000101111100000111000001111101111100100001000010000100100011000110001100010111010001100011000101010001001000110001101011010"+
// // "1011101000101010001000101010001100010101000100001000010011111000100010001000111110010001100001000010001110011101000100010001001111111110000010011"+
// // "0000011111010010100101111100010000101111110000111100000111110011111000011110100010111011111000010001000100001000111010001011101000101110011101000"+
// // "1011110000101110011101000110001100010111000000000000000000000111110010000100001000000000100111111000110111101011011101010111110101011111010100000"+
// // "000000000000000000100001100001000100000000000011011010011001000000000000111010001001100000000100000010001000100010001000000010001000100000100000100001000100001000010000010"
//
// },
laser: {
"osc1_oct": 7,
"osc1_det": 0,
"osc1_detune": 0,
"osc1_xenv": 1,
"osc1_vol": 255,
"osc1_waveform": 3,
"osc2_oct": 8,
"osc2_det": 0,
"osc2_detune": 0,
"osc2_xenv": 1,
"osc2_vol": 255,
"osc2_waveform": 0,
"noise_fader": 61,
"env_attack": 22,
"env_sustain": 22,
"env_release": 21759,
"env_master": 255,
"fx_filter": 3,
"fx_freq": 4067,
"fx_resonance": 176,
"fx_delay_time": 4,
"fx_delay_amt": 12,
"fx_pan_freq": 2,
"fx_pan_amt": 84,
"lfo_osc1_freq": 0,
"lfo_fx_freq": 1,
"lfo_freq": 3,
"lfo_amt": 96,
"lfo_waveform": 0
},
};
//--this gets wrapped in a closure, so no namespace object, compresses better.
const WIDTH = 512;
const HEIGHT = 256;
var
C = document.getElementById('canvas');
ctx = C.getContext('2d'),
renderTarget = 0x00000,
renderSource = 0x20000,
//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 = WIDTH;
C.height = HEIGHT;
var imageData = ctx.getImageData(0, 0, 512, 256),
buf = new ArrayBuffer(imageData.data.length),
buf8 = new Uint8Array(buf),
data = new Uint32Array(buf),
ram = new Uint8ClampedArray(0x100000);
//--------------graphics functions----------------
function clear(color){
ram.fill(color, renderTarget, renderTarget + 0x20000);
}
function pset(x, y, color) { //from colors array, 0-31
x = x|0; y = y|0; color = color|0;
if (x > -1 && x < WIDTH && y > -1 && y < HEIGHT) {
ram[renderTarget + (y * WIDTH + 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 < HEIGHT && x+j < WIDTH && y+i > -1 && x+j > -1){
if(flipx & flipy){
if(ram[(renderSource + ( ( sy + (sh-i) )*WIDTH+sx+(sw-j)))] > 0) {
ram[ (renderTarget + ((y+i)*WIDTH+x+j)) ] = pal[ ram[(renderSource + ((sy+(sh-i))*WIDTH+sx+(sw-j)))] ];
}
}
else if(flipy && !flipx){
if(ram[(renderSource + ( ( sy + (sh-i) )*WIDTH+sx+j))] > 0) {
ram[ (renderTarget + ((y+i)*WIDTH+x+j)) ] = ram[(renderSource + ((sy+(sh-i))*WIDTH+sx+j))];
}
}
else if(flipx && !flipy){
if(ram[(renderSource + ((sy+i)*WIDTH+sx+(sw-j)))] > 0) {
ram[ (renderTarget + ((y+i)*WIDTH+x+j)) ] = ram[(renderSource + ((sy+i)*WIDTH+sx+(sw-j)))];
}
}
else if(!flipx && !flipy){
if(ram[(renderSource + ((sy+i)*WIDTH+sx+j))] > 0) {
ram[ (renderTarget + ((y+i)*WIDTH+x+j)) ] = pal[ ram[(renderSource + ((sy+i)*WIDTH+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 < HEIGHT && x+j < WIDTH && y+i > -1 && x+j > -1) {
if (ram[(renderSource + ((sy + py) * WIDTH + sx + px))] > 0) {
ram[(renderTarget + ((y + i) * WIDTH + x + j))] = ram[(renderSource + ((sy + py) * WIDTH + 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 * WIDTH + u)) ] > 0) {
ram[(renderTarget + (drawY * WIDTH + drawX)) ] = ram[(renderSource + ( v * WIDTH + 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 = 0x20000; // display is first 0x20000 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);
}
playSound = function(buffer, playbackRate, pan, loop) {
var source = audioCtx.createBufferSource();
var gainNode = audioCtx.createGain();
var panNode = audioCtx.createStereoPanner();
source.buffer = buffer;
source.connect(panNode);
panNode.connect(gainNode);
gainNode.connect(audioCtx.destination);
//gainNode.connect(audioCtx.destination);
source.playbackRate.value = playbackRate;
source.loop = loop;
gainNode.gain.value = 1;
panNode.pan.value = pan;
source.start();
return {volume: gainNode, sound: source};
}
init = function(){
last = 0;
dt = 0;
now = 0;
t = 0;
moveX = 0;
speedFactor = .6;
songTrigger = false;
state = 'menu';
demostate = 0;
audioCtx = new AudioContext;
fontString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_!@.'\"?/<()";
fontBitmap = "11111100011111110001100011111010001111101000111110111111000010000100000111111100100101000110001111101111110000111001000011111111111000"+
"0111001000010000111111000010111100011111110001100011111110001100011111100100001000010011111111110001000010100101111010001100101110010010100011000"+
"0100001000010000111111000111011101011000110001100011100110101100111000101110100011000110001011101111010001100101110010000011101000110001100100111"+
"1111101000111110100011000101111100000111000001111101111100100001000010000100100011000110001100010111010001100011000101010001001000110001101011010"+
"1011101000101010001000101010001100010101000100001000010011111000100010001000111110010001100001000010001110011101000100010001001111111110000010011"+
"0000011111010010100101111100010000101111110000111100000111110011111000011110100010111011111000010001000100001000111010001011101000101110011101000"+
"1011110000101110011101000110001100010111000000000000000000000111110010000100001000000000100111111000110111101011011101010111110101011111010100000"+
"000000000000000000100001100001000100000000000011011010011001000000000000111010001001100000000100000010001000100010001000000010001000100000100000100001000100001000010000010"
// asciiBinary = '~cQz??I#_CH?|Ba<?FcdO~Rz90B?uFs,q:bwQKH 2?h} /A`}yHc .FT$1VW"Q'+
// 'F!D>#g"xtR|!?Ayx= _"t.Eg"x.:bpH!xo-j}/TC mQ@" BB';
//console.log( getCharacter('A') );
//console.log( assets.font.string.length );
//console.log( flattenArray() );
//console.log( binToAscii(assets.font.bigString) );
//console.log( asciiToBin('~cQz??I#_CH?|Ba<?FcdO~Rz90B?uFs,q:bwQKH 2?h} /A`}yHc .FT$1VW"Q'+ 'F!D>#g"xtR|!?Ayx= _"t.Eg"x.:bpH!xo-j}/TC mQ@" BB'));
//assets.font.bigString = asciiToBin(assets.font.bin);
//fontBitmap = (function(asciiBinary,b,i){b="";for(i in asciiBinary)b+=(1e7+s.charCodeAt(i).toString(2)).slice(-7);return b})();
bulletPool = new Pool(100, Particle);
sounds = {};
stats = new Stats();
document.body.appendChild( stats.dom );
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);
}
soundInit = () => {
sounds = {};
//if(audioCtx){audioCtx.close()};
window.AudioContext = window.AudioContext || window.webkitAudioContext;
if(!audioCtx) audioCtx = new AudioContext;
let soundGen = new sonantx.SoundGenerator(assets.laser);
soundGen.createAudioBuffer(147, function(buffer) {
sounds.laser = buffer;
});
}
eventInit = () => {
//initialize keypress event listeners
window.addEventListener('keyup', function (event) {
Key.onKeyup(event);
}, false);
window.addEventListener('mousedown', function (event){
stopCapture(event);
}, false);
window.addEventListener('keydown', function (event) {
Key.onKeydown(event);
}, false);
window.addEventListener('blur', function (event) {
paused = true;
}, false);
window.addEventListener('focus', function (event) {
paused = false;
}, false);
}
states.gameover = {
step: function(dt) {
if(Key.isDown(Key.r)){
state = 'menu';
}
},
render: function(dt) {
renderTarget = 0x0;
clear(0);
//fr(0,0,64,64,2);
text({
x: 256,
y: 80 + Math.sin(t*2.5)*15,
text: 'GAME OVER',
hspacing: 8 + Math.cos(t*2.9)*4,
vspacing: 15 + Math.sin(t*3.5)*5,
halign: 'center',
valign: 'top',
scale: 9,
snap: 1,
render: 1,
color: 27,
});
},
};
states.menu = {
step: function(dt) {
//game update
if(Key.isDown(Key.p)){
state = 'game';
}
},
render: function(dt) {
renderTarget = 0x0;
clear(0);
let s = 256;
let i = t/3;
for(let y = -128; y < 128; y += 1 ){
for(let x = -256; x < 256; x += 2 ){
pset(s+x+256*Math.cos( (y/128+i)*4 )+y, s+y+128*Math.sin( (x/256+i)*4 )+x, x/8%32)
}
}
text({
x: 256,
y: 40 + Math.sin(t*2.5)*15,
text: 'PROTOGAME',
hspacing: 8 + Math.cos(t*2.9)*4,
vspacing: 15 + Math.sin(t*3.5)*5,
halign: 'center',
valign: 'top',
scale: 9,
snap: 1,
render: 1,
color: 21,
});
text({
x: 256,
y: 230,
text: "PRESS P TO CONTINUE",
hspacing: 2,
vspacing: 2,
halign: 'center',
valign: 'top',
scale: 1,
snap: 1,
render: 1,
color: 21,
});
//draw stuff here.
},
};
states.game = {
step(dt) {
player.update(dt);
//----hacky sound test
if(Key.justReleased(Key.SPACE)){
songTrigger = true
}
if(songTrigger){
playSound(sounds.laser, 1, 1, 0);
songTrigger = false;
}
//---end hacky sound test
bulletPool.use();
Key.update();
},
render(dt) {
renderTarget = 0x0;
//background dot waves
clear(1);
let s = 256;
let i = t/3;
for(let y = -128; y < 128; y += 1 ){
for(let x = -256; x < 256; x += 2 ){
pset(s+x+256*Math.cos( (y/128+i)*4 )+y, s+y+128*Math.sin( (x/256+i)*4 )+x, x/8%32)
}
}
//foreground octopus thing
renderTarget = 0x40000; //rendering to different area, for collision checks and composite effects.
clear(0);
for(var a = 0; a < 2 * Math.PI; a+= 0.7){
for(var r = 20; r < 200; r += 9){
let v = a + .4 * Math.sin(a*8-r/20+t*1.7);
fillCircle((256+r*Math.cos(v)), 80+r*Math.sin(v), (10-r/12)|0, 10+(r/9%32)|0 );
}
}
renderTarget = 0x0;
renderSource = 0x40000;
spr(0,0,512,256);
player.draw();
renderTarget = 0;
text({
x: 256,
y: 20,
text: "YOU CANT DEFEAT HIM, THIS IS JUST A PIXEL-PERFECT COLLISION\nAND MULTI-LAYER DRAWING DEMO\nARROW KEYS OR WASD AND SPACE TO SHOOT",
hspacing: 2,
vspacing: 2,
halign: 'center',
valign: 'top',
scale: 1,
snap: 1,
render: 1,
color: 21,
});
},
};
function drawExplode(x,y){
fillCircle(x,y, 20, 21);
}
function textLine(opt) {
var textLength = opt.text.length,
size = 5;
for (var i = 0; i < textLength; i++) {
var letter = [];
letter = getCharacter( opt.text.charAt(i) );
//console.log(letter);
//console.log(assets.letters[ opt.text.charAt(i)]);
for (var y = 0; y < size; y++) {
for (var x = 0; x < size; x++) {
//if (letter[y][x] == 1) {
if (letter[y*size+x] == 1){
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);
}
} //end draw routine
} //end x loop
} //end y loop
} //end text loop
} //end textLine()
function 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);
}
textLine({
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
}
}
function getCharacter(char){
index = fontString.indexOf(char);
return fontBitmap.substring(index * 25, index*25+25).split('') ;
}
// function flattenArray(){
// var bigString = "";
// bin = assets.font.bin;
// for(var i = 0; i < assets.font.string.length; i++){
// for(var j = 0; j < 5; j++){
// bigString += bin[j][0].substring(i * 5, i*5+5);
// }
// }
// console.log(bigString);
// return bigString;
// }
// function binToAscii(b,a,i){
// a="";
// for(i=0;i<b.length;i+=7)a+=String.fromCharCode(parseInt(b.substr(i,7),2));
// return a
// }
//function asciiToBin(s,b,i){b="";for(i in s)b+=(1e7+s.charCodeAt(i).toString(2)).slice(-7);return b}
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 > WIDTH){
player.x = 0;
}
if(player.x < 0){
player.x = WIDTH;
}
if(player.y > HEIGHT){
player.y = 0;
}
if(player.y < 0){
state = 'gameover';
player.y = HEIGHT;
}
//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);
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment