├── index.js ├── src ├── post.js ├── pre.js ├── definitions.js ├── env_prod.js ├── shaders │ ├── static.vert │ └── badcolor.frag ├── player.js ├── canvasRenderer.js ├── index.html ├── tiles.js ├── backgroundEffects.js ├── gameloop.js ├── webglRenderer.js ├── env_dev.js ├── effects.js ├── sounds.js ├── font.js ├── collisionHandler.js ├── items.js ├── levelUpScene.js ├── spriteLoader.js ├── scene.js ├── gameObject.js ├── gameHud.js ├── theScript.js ├── generatedSprites.js ├── gameSetup.js ├── fighterController.js └── fighter.js ├── scripts ├── wrapjs.sh ├── compileglsfiles.sh └── concat.sh ├── README.md ├── assets ├── hero17.sprite ├── hero18.sprite ├── hero19.sprite ├── hero20.sprite ├── hero21.sprite ├── hero22.sprite ├── hero08_jump_01.sprite ├── hero05_run_02.sprite ├── hero16_defeated_00.sprite ├── hero14_knocked_down_00.sprite ├── hero11_get_hit_face_00.sprite ├── hero12_get_hit_body_00.sprite ├── hero13_get_hit_legs_00.sprite ├── hero06_speed_punch_00.sprite ├── hero10_dragon_kick_00.sprite ├── hero15_wake_up_00.sprite ├── hero08_jump_00.sprite ├── hero02_punch_01.sprite ├── hero02_punch_02.sprite ├── hero03_kick_01.sprite ├── hero03_kick_02.sprite ├── hero09_air_kick_00.sprite ├── hero08_jump_02.sprite ├── hero04_walk_00.sprite ├── hero01_idle_00.sprite ├── hero07_speed_kick_00.sprite ├── z_explosion_02.sprite ├── z_explosion_01.sprite ├── z_tilemap_00.sprite ├── hero05_run_01.sprite └── fonts.sprite ├── lib ├── utils.js ├── keyboardController.js ├── audio.js ├── stats.min.js ├── webgl.js └── jsfxr.js ├── script.temp ├── todo ├── LICENSE.txt ├── .gitignore ├── spriteChangeSide.js ├── sprite.temp ├── package.json └── spriteConverter.js /index.js: -------------------------------------------------------------------------------- 1 | console.log('index.js?') -------------------------------------------------------------------------------- /src/post.js: -------------------------------------------------------------------------------- 1 | // ending wrap code 2 | })(); -------------------------------------------------------------------------------- /src/pre.js: -------------------------------------------------------------------------------- 1 | // start wrapping code 2 | (function() { 3 | -------------------------------------------------------------------------------- /src/definitions.js: -------------------------------------------------------------------------------- 1 | 2 | var W = 320; 3 | var H = 240; 4 | 5 | var c = document.getElementById('c'); 6 | var g = document.getElementById('g'); -------------------------------------------------------------------------------- /src/env_prod.js: -------------------------------------------------------------------------------- 1 | const DEBUG = false; // eslint-disable-line no-unused-vars 2 | var _fps_ 3 | var _processing_ 4 | var _memory_ 5 | var _enemies_ 6 | 7 | -------------------------------------------------------------------------------- /src/shaders/static.vert: -------------------------------------------------------------------------------- 1 | attribute vec2 p; 2 | varying vec2 uv; 3 | 4 | void main() { 5 | gl_Position = vec4(p,.0,1.); 6 | uv = .5 * (p+1.); 7 | } -------------------------------------------------------------------------------- /src/player.js: -------------------------------------------------------------------------------- 1 | // src/player.js >>> 2 | 3 | 4 | var player = Fighter([8, 120, FIGHTER_STATUS_IDS[0], '#ddfed9']); 5 | var basePlayerStat = { 6 | maxHp: 30, 7 | damage: 0, 8 | defense: 0 9 | }; 10 | -------------------------------------------------------------------------------- /scripts/wrapjs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # original script from @gre 3 | # https://github.com/gre/behind-asteroids/blob/master/scripts/wrapjs.sh 4 | # usage: cat glslfile | ./wrapjs.sh varname 5 | 6 | echo -n "var $1 ='" 7 | perl -p -e 's/\n/\\n/'; 8 | echo -ne "';" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # js13k2018 2 | Without a code name... yet... 3 | 4 | 5 | # npm packages 6 | - https://www.npmjs.com/package/nodemon 7 | 8 | ## installation 9 | 10 | `npm run install` 11 | 12 | ## live-reload server 13 | 14 | `npm run start` 15 | 16 | ## build zip generator 17 | 18 | `npm run build` -------------------------------------------------------------------------------- /src/canvasRenderer.js: -------------------------------------------------------------------------------- 1 | // src/canvasRenderer.js >>> 2 | 3 | var graphics = c.getContext('2d'); 4 | 5 | var animationIndex = 0; 6 | var pixelSize = 2; 7 | var frames = animations[0]; 8 | 9 | function draw() { 10 | 11 | drawBackground(); 12 | sceneManager.draw(); 13 | } 14 | 15 | // ending file 16 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | JS13K 2018 @agar3s -------------------------------------------------------------------------------- /src/tiles.js: -------------------------------------------------------------------------------- 1 | // src/tiles.js 2 | 3 | function Tile(props) { 4 | var base = Sprite([props[0], props[1], 30]); 5 | base.frame = base.animation[props[2]]; 6 | base.color = '#ddfed9'; 7 | base.pixelSize = 2; 8 | var extended = { 9 | update: function(){} 10 | } 11 | extendFunction(base, extended); 12 | return extended; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /assets/hero17.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | _______MM_______ 5 | _______MM_______ 6 | ______MM________ 7 | ______MM_M______ 8 | ______MMM_______ 9 | ______MM________ 10 | _______MM_______ 11 | _______M_M______ 12 | _______M__M_____ 13 | _______M__M_____ 14 | ______M__M______ 15 | ______M__M______ 16 | _____M___M______ 17 | Animation: 18 | 0 -------------------------------------------------------------------------------- /assets/hero18.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | _______MM_______ 5 | _______MM_______ 6 | ______MM________ 7 | ______MM_M______ 8 | ______MMM_______ 9 | ______MM________ 10 | _______MM_______ 11 | _______M_M______ 12 | _______M__M_____ 13 | _______M__M_____ 14 | ______M__M______ 15 | ______M__M______ 16 | _____M___M______ 17 | Animation: 18 | 0 -------------------------------------------------------------------------------- /assets/hero19.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | _______MM_______ 5 | _______MM_______ 6 | ______MM________ 7 | ______MM_M______ 8 | ______MMM_______ 9 | ______MM________ 10 | _______MM_______ 11 | _______M_M______ 12 | _______M__M_____ 13 | _______M__M_____ 14 | ______M__M______ 15 | ______M__M______ 16 | _____M___M______ 17 | Animation: 18 | 0 -------------------------------------------------------------------------------- /assets/hero20.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | _______MM_______ 5 | _______MM_______ 6 | ______MM________ 7 | ______MM_M______ 8 | ______MMM_______ 9 | ______MM________ 10 | _______MM_______ 11 | _______M_M______ 12 | _______M__M_____ 13 | _______M__M_____ 14 | ______M__M______ 15 | ______M__M______ 16 | _____M___M______ 17 | Animation: 18 | 0 -------------------------------------------------------------------------------- /assets/hero21.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | _______MM_______ 5 | _______MM_______ 6 | ______MM________ 7 | ______MM_M______ 8 | ______MMM_______ 9 | ______MM________ 10 | _______MM_______ 11 | _______M_M______ 12 | _______M__M_____ 13 | _______M__M_____ 14 | ______M__M______ 15 | ______M__M______ 16 | _____M___M______ 17 | Animation: 18 | 0 -------------------------------------------------------------------------------- /assets/hero22.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | _______MM_______ 5 | _______MM_______ 6 | ______MM________ 7 | ______MM_M______ 8 | ______MMM_______ 9 | ______MM________ 10 | _______MM_______ 11 | _______M_M______ 12 | _______M__M_____ 13 | _______M__M_____ 14 | ______M__M______ 15 | ______M__M______ 16 | _____M___M______ 17 | Animation: 18 | 0 -------------------------------------------------------------------------------- /assets/hero08_jump_01.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________MM______ 3 | ______MMMM______ 4 | _____M_MM_______ 5 | _____M_MMM______ 6 | _____M_MM_______ 7 | _______M________ 8 | _______MMM______ 9 | ________M_M_____ 10 | ________M_M_____ 11 | ________MM______ 12 | _______MM_______ 13 | _______M________ 14 | _______M________ 15 | _______M________ 16 | ________________ 17 | Animation: 18 | 0 -------------------------------------------------------------------------------- /assets/hero05_run_02.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | ______MM________ 6 | ______MM________ 7 | ______MMM_M_____ 8 | _____M_MMM______ 9 | ______MMM_______ 10 | ________M_______ 11 | ________MM______ 12 | ________M_M_____ 13 | ________M__M____ 14 | ________M__M____ 15 | _______M____M___ 16 | _______M_____M__ 17 | Animation: 18 | 0,0,0 -------------------------------------------------------------------------------- /assets/hero16_defeated_00.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | ________________ 6 | ________________ 7 | ________________ 8 | ________________ 9 | ________________ 10 | ________________ 11 | ________________ 12 | ________________ 13 | ________________ 14 | ________________ 15 | __MMMMMM________ 16 | MMMMMMMMMMMMMMMM 17 | Animation: 18 | 0 -------------------------------------------------------------------------------- /assets/hero14_knocked_down_00.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | _____M__________ 6 | _CC__M__________ 7 | _CC__M__________ 8 | __CCC___________ 9 | __CCCC__________ 10 | __M__MMMMM______ 11 | __M___MM__M_____ 12 | ___M____M_M_____ 13 | _______M___M____ 14 | _______M___M____ 15 | ______M_________ 16 | ______M_________ 17 | Animation: 18 | 0 -------------------------------------------------------------------------------- /assets/hero11_get_hit_face_00.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | _____MM_________ 6 | _____MM_________ 7 | _____MMM________ 8 | _____MMMM_______ 9 | ____M_MM________ 10 | ______MM________ 11 | ______MMM_______ 12 | _______MM_______ 13 | _______M_M______ 14 | _______M_M______ 15 | _______M__M_____ 16 | ______M___M_____ 17 | Animation: 18 | 0,0,0 -------------------------------------------------------------------------------- /assets/hero12_get_hit_body_00.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | ________________ 6 | _________MM_____ 7 | ________MMM_____ 8 | _______MMM______ 9 | _______MM_______ 10 | _______MM_______ 11 | _______M________ 12 | _______MM_______ 13 | _______M_M______ 14 | ________M_M_____ 15 | _______M__M_____ 16 | ______M__M______ 17 | Animation: 18 | 0,0,0 -------------------------------------------------------------------------------- /assets/hero13_get_hit_legs_00.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | ___________MM___ 6 | _________MMMM___ 7 | ________MMM_____ 8 | _______MMM_M____ 9 | _______MM_M_MM__ 10 | ______MM________ 11 | ___M__MMM_______ 12 | ____M_M__M______ 13 | _____M___M______ 14 | _______MM_______ 15 | ______M_________ 16 | ________________ 17 | Animation: 18 | 0,0,0,0 -------------------------------------------------------------------------------- /assets/hero06_speed_punch_00.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | ________________ 6 | __________MM____ 7 | _______MM_MM____ 8 | ______M__CCCCCCC 9 | ________MMM_____ 10 | _______MM_______ 11 | ______MM________ 12 | _____M__MM______ 13 | ___MM_____M_____ 14 | __M_____MM______ 15 | _M_____M________ 16 | M______M________ 17 | Animation: 18 | 0,0,0,0,0,0 -------------------------------------------------------------------------------- /assets/hero10_dragon_kick_00.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | ____MM__________ 6 | ____MM__________ 7 | ___MMM_M________ 8 | ___MMMM_________ 9 | __M__MM_________ 10 | ___M__MMM_______ 11 | ______MMMM______ 12 | __________MM____ 13 | _________MM_C___ 14 | _____________CC_ 15 | ______________CC 16 | ________________ 17 | Animation: 18 | 0,0,0,0,0,0 -------------------------------------------------------------------------------- /assets/hero15_wake_up_00.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | ________________ 6 | ________________ 7 | ________________ 8 | ________________ 9 | ________________ 10 | ________________ 11 | ________________ 12 | _______MMMM_____ 13 | ______MMMMMMM___ 14 | ______MM__MMM___ 15 | ___MMMMM__M_____ 16 | __M_MMMMM__M____ 17 | Animation: 18 | 0,0,0,0,0,0,0,0,0,0,0,0,0 -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | 2 | var getRandomValue = function(value, offset) { 3 | return Math.random()*(value||1) + (offset||0); 4 | } 5 | 6 | var randomSign = function() { 7 | return getRandomValue()>0.5?1:-1; 8 | } 9 | 10 | var extendFunction = function(parent, child) { 11 | var keys = Object.keys(parent); 12 | for(var i=0; i= flashEffect[0]) { 21 | flashEffect[3] = 0; 22 | currentBackground = '#0c1d05'; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /scripts/compileglsfiles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # original script from @gre 3 | # https://github.com/gre/behind-asteroids/blob/master/scripts/compileglsfiles.sh 4 | 5 | if [ "$#" -ne 2 ]; then 6 | echo "Invalid arguments. Usage: $0 fromDir toDir" >&2; 7 | exit 1; 8 | fi; 9 | if [ "$1" == "$2" ]; then 10 | echo "fromDir and toDir must be different" >&2; 11 | exit 2; 12 | fi; 13 | if [ ! -d "$1" ]; then 14 | echo "fromDir must be a directory" >&2; 15 | exit 3; 16 | fi; 17 | if [ ! -d "$2" ]; then 18 | echo "toDir must be a directory" >&2; 19 | exit 4; 20 | fi; 21 | 22 | for glsl in $1/*.frag $1/*.vert; do 23 | name=`basename $glsl`; 24 | cat $glsl | glslmin > $2/$name; 25 | done; 26 | -------------------------------------------------------------------------------- /src/gameloop.js: -------------------------------------------------------------------------------- 1 | // src/gameLoop.js >>> 2 | 3 | var timeEnd = 0; 4 | function loop(time) { 5 | if(DEBUG){ 6 | _fps_.begin(); 7 | _processing_.begin(); 8 | _memory_.begin(); 9 | _enemies_.begin(); 10 | } 11 | var dt = time - timeEnd; 12 | var refreshRatio = dt/1000; 13 | timeEnd = time; 14 | resetMatrix(); 15 | updateBackgroud(refreshRatio); 16 | sceneManager.update(time, refreshRatio); 17 | 18 | draw(); 19 | // drawPostProcessing(~~(time)); 20 | requestAnimationFrame(loop); 21 | 22 | if(DEBUG){ 23 | _fps_.end(); 24 | _processing_.end(); 25 | _memory_.end(); 26 | _enemies_.end(); 27 | //enemiesPanel.update(enemies?enemies.length:0, 1000); 28 | } 29 | } 30 | 31 | loop(1); 32 | -------------------------------------------------------------------------------- /assets/hero08_jump_00.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | ________________ 6 | ________MM______ 7 | ________MM______ 8 | _______MM_______ 9 | ______MMM_M_____ 10 | ______MMMM______ 11 | _______M________ 12 | _______MMMM_____ 13 | ________M__M____ 14 | ________M_M_____ 15 | _______M__M_____ 16 | ______M___M_____ 17 | //new Frame 18 | ________________ 19 | ________________ 20 | ________MM______ 21 | _______MMM______ 22 | ______MMM_M_____ 23 | ______MMMM______ 24 | ______MM________ 25 | _______MM_______ 26 | _______MMM______ 27 | ________M_M_____ 28 | ________M_M_____ 29 | _______M_M______ 30 | ______M__M______ 31 | _____M__M_______ 32 | ________M_______ 33 | ________________ 34 | Animation: 35 | 0,1 -------------------------------------------------------------------------------- /assets/hero02_punch_01.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | _______MM_______ 5 | _______MM_______ 6 | ______MM________ 7 | ______MM_M______ 8 | ______MMM_______ 9 | ______MM________ 10 | _______MM_______ 11 | _______M_M______ 12 | _______M__M_____ 13 | _______M__M_____ 14 | ______M__M______ 15 | ______M__M______ 16 | _____M___M______ 17 | //new Frame 18 | ________________ 19 | ________________ 20 | ________________ 21 | _______MM_______ 22 | ______CCCCCCCC__ 23 | _____MMM________ 24 | _____MMM________ 25 | ______MM________ 26 | ______MM________ 27 | _______MM_______ 28 | _______M_M______ 29 | _______M__M_____ 30 | _______M__M_____ 31 | ______M__M______ 32 | ______M__M______ 33 | _____M___M______ 34 | Animation: 35 | 0,1,1,0 -------------------------------------------------------------------------------- /assets/hero02_punch_02.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | _______MM_______ 5 | _______MM_______ 6 | ______MM________ 7 | ______MM_M______ 8 | ______MMM_______ 9 | ______MM________ 10 | _______MM_______ 11 | _______M_M______ 12 | _______M__M_____ 13 | _______M__M_____ 14 | ______M__M______ 15 | ______M__M______ 16 | _____M___M______ 17 | //new Frame 18 | ________________ 19 | ________________ 20 | ________________ 21 | ________________ 22 | ________MM______ 23 | ________MM______ 24 | _______MCC______ 25 | ______MMM_CC____ 26 | _______MM___CC__ 27 | _______MM_______ 28 | _______MMM______ 29 | ______M___M_____ 30 | ______M___M_____ 31 | _____M___M______ 32 | _____M___M______ 33 | ____M____M______ 34 | Animation: 35 | 0,1,1,0 -------------------------------------------------------------------------------- /assets/hero03_kick_01.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ____MM__________ 5 | ____MM__________ 6 | ____MMM_________ 7 | ____MMMM________ 8 | ____M_MMM_______ 9 | ______M_MM______ 10 | ______MM__M_____ 11 | ______M___M_____ 12 | ______M___M_____ 13 | ______M_________ 14 | ______M_________ 15 | _____M__________ 16 | _____M__________ 17 | //new Frame 18 | ________________ 19 | ________________ 20 | ________________ 21 | ____MM__________ 22 | ____MM__________ 23 | ____MMM_________ 24 | ____MMMM________ 25 | ____M_CCCCCCCCC_ 26 | ______M_________ 27 | ______M_________ 28 | ______M_________ 29 | ______M_________ 30 | ______M_________ 31 | ______M_________ 32 | _____M__________ 33 | _____M__________ 34 | Animation: 35 | 0,1,1,1,0,0 -------------------------------------------------------------------------------- /assets/hero03_kick_02.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ____MM__________ 5 | ____MM__________ 6 | ____MMM_________ 7 | ____MMMM________ 8 | ___M_MM_________ 9 | ______M_MM______ 10 | ______MM__M_____ 11 | ______M___M_____ 12 | ______M___M_____ 13 | ______M_________ 14 | ______M_________ 15 | _____M__________ 16 | _____M__________ 17 | //new Frame 18 | ________________ 19 | ________________ 20 | ________________ 21 | ____MM________C_ 22 | ____MMM______CC_ 23 | ____MMMM___CC___ 24 | ____MMM__CC_____ 25 | ___MM_MMM_______ 26 | ______M_________ 27 | ______M_________ 28 | ______M_________ 29 | ______M_________ 30 | ______M_________ 31 | ______M_________ 32 | ______M_________ 33 | _____M__________ 34 | Animation: 35 | 0,1,1,1,0,0 -------------------------------------------------------------------------------- /assets/hero09_air_kick_00.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________MM______ 3 | ______MMMM______ 4 | _____M_MM_______ 5 | _____M_MMM______ 6 | _______MM_______ 7 | _______M________ 8 | _______MMMM_____ 9 | ________M__M____ 10 | ________M__M____ 11 | ________M__M____ 12 | _______M__M_____ 13 | ______M_________ 14 | ________________ 15 | ________________ 16 | ________________ 17 | //new Frame 18 | ________________ 19 | ________MM______ 20 | ______MMMM______ 21 | _____MMMM_______ 22 | _______MMM______ 23 | _______MM_______ 24 | _______M________ 25 | _______MMMMCCCC_ 26 | _______MM_______ 27 | _____MMMM_______ 28 | ________________ 29 | ________________ 30 | ________________ 31 | ________________ 32 | ________________ 33 | ________________ 34 | Animation: 35 | 0,1,1 -------------------------------------------------------------------------------- /src/webglRenderer.js: -------------------------------------------------------------------------------- 1 | // src/webglRenderer.js 2 | var glprops = {preserveDrawingBuffer: true}; 3 | var gl = g.getContext('webgl', glprops) || g.getContext('experimental-webgl', glprops); 4 | 5 | // webgl setup 6 | gl.viewport(0, 0, W, H); 7 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); 8 | 9 | var buffer = gl.createBuffer(); 10 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 11 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 12 | -1.0, -1.0, 13 | 1.0, -1.0, 14 | -1.0, 1.0, 15 | -1.0, 1.0, 16 | 1.0, -1.0, 17 | 1.0, 1.0 18 | ]), gl.STATIC_DRAW); 19 | 20 | var badColorShader = glCreateShader(STATIC_VERT, BADCOLOR_FRAG); 21 | gl.uniform2f(glUniformLocation(badColorShader, 'dim'), W, H); 22 | 23 | var fbo1 = glCreateFBO(); 24 | var fbo2 = glCreateFBO(); 25 | 26 | var textureGame = glCreateTexture(); 27 | -------------------------------------------------------------------------------- /lib/keyboardController.js: -------------------------------------------------------------------------------- 1 | 2 | var keyMap = 0; 3 | // default keyboard 4 | var inputs = { 5 | UP: 38, 6 | DOWN: 40, 7 | LEFT: 37, 8 | RIGHT: 39, 9 | PUNCH: 83, 10 | KICK: 68, 11 | JUMP: 32, 12 | ENTER: 13, 13 | ESC: 27 14 | }; 15 | 16 | var keys = {}; 17 | var inputNames = Object.keys(inputs); 18 | for (var i = 0; i < inputNames.length; i++) { 19 | var inputName = inputNames[i]; 20 | keys[inputs[inputName]] = (1< js13k 22 | > colisiones 23 | > generar impactos 24 | esta es la clave de este juego. 25 | SoundBox 26 | > get 27 | 28 | > evil glitch 29 | > unreal 30 | 31 | > phaser boilerplate engine 32 | 33 | ahora los sprites pueden tener areas de impacto. 34 | cabeza 1 - 6 35 | tronco 7 - 11 36 | pies? 12 - 16 37 | 38 | 39 | diseño de evil glitch 40 | y hacerlo en unity 41 | 42 | js13k 43 | leer el libro de manufacturing consent 44 | 45 | +- quiero saber si pego arriba, medio o abajo 46 | +- agregar efecto de fondo 47 | +- mostrar una chispita o algo cuando haga hit 48 | +- animar el golpe dependiendo de la ubicacion 49 | +- separate sprite de actor 50 | 51 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Giovanny Beltran 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | # skip dist files 64 | dist 65 | package-lock.json 66 | target* 67 | *.exe 68 | *.ini 69 | -------------------------------------------------------------------------------- /src/font.js: -------------------------------------------------------------------------------- 1 | // src/font.js 2 | 3 | var fontLetters = 'abcdefghijklmnopqrstuvwxyz0123456789!?# :,.’+()><'; 4 | var indexOfFontFrame = 0; 5 | 6 | function parseText(text) { 7 | var indexes = []; 8 | for (var i = 0; i < text.length; i++) { 9 | indexes.push(fontLetters.indexOf(text[i])); 10 | } 11 | return indexes; 12 | } 13 | 14 | function drawFrame(index, size) { 15 | var letterFrame = animations[indexOfFontFrame][index]; 16 | for (var i = 0; i < letterFrame.length; i++) { 17 | var coords = letterFrame[i]; 18 | graphics.fillRect(coords[0]*size, coords[1]*size, size, size); 19 | } 20 | } 21 | 22 | function Text(props) { 23 | var base = GameObject(props); 24 | var indexes = parseText(props[2]); 25 | return { 26 | x: base.x, 27 | y: base.y, 28 | visible: true, 29 | color: '#ddfed9', 30 | size: 1, 31 | update: base.update, 32 | setText: function(text) { 33 | indexes = parseText(text); 34 | }, 35 | draw: function() { 36 | graphics.fillStyle = this.color; 37 | for (var i = 0; i < indexes.length; i++) { 38 | graphics.save(); 39 | graphics.translate((~~this.x) + i*7*this.size, (~~this.y)); 40 | drawFrame(indexes[i], this.size); 41 | graphics.restore(); 42 | } 43 | } 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /scripts/concat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # original script from @gre 3 | # https://github.com/gre/behind-asteroids/blob/master/scripts/concat.sh 4 | echo "// larga vida al #js13k! " 5 | # pre 6 | cat src/pre.js 7 | 8 | if [ "$NODE_ENV" == "production" ]; then 9 | cat src/env_prod.js 10 | else 11 | cat lib/stats.min.js 12 | cat src/env_dev.js 13 | fi; 14 | 15 | # definitions 16 | cat src/definitions.js 17 | 18 | # libs 19 | cat lib/utils.js 20 | cat lib/jsfxr.js 21 | cat lib/audio.js 22 | #cat lib/webgl.js 23 | cat lib/keyboardController.js 24 | 25 | # shaders 26 | #cd dist; 27 | #for glsl in *.frag *.vert; do 28 | # name=`echo $glsl | tr '.' '_' | tr '[:lower:]' '[:upper:]'` 29 | # cat $glsl | ../scripts/wrapjs.sh $name 30 | # echo 31 | #done 32 | #cd ..; 33 | 34 | # game 35 | cat src/generatedSprites.js 36 | cat src/theScript.js 37 | cat src/spriteLoader.js 38 | cat src/gameObject.js 39 | cat src/items.js 40 | cat src/fighter.js 41 | cat src/font.js 42 | cat src/tiles.js 43 | cat src/sounds.js 44 | cat src/collisionHandler.js 45 | 46 | cat src/backgroundEffects.js 47 | 48 | cat src/fighterController.js 49 | cat src/player.js 50 | 51 | cat src/canvasRenderer.js 52 | #cat src/webglRenderer.js 53 | #cat src/effects.js 54 | cat src/scene.js 55 | cat src/gameSetup.js 56 | cat src/gameHud.js 57 | cat src/levelUpScene.js 58 | cat src/gameloop.js 59 | cat src/post.js 60 | -------------------------------------------------------------------------------- /spriteChangeSide.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var dir = './assets'; 3 | 4 | //assuming sprites with 16X16 dimmension 5 | var cols = 16; 6 | var rows = 16; 7 | 8 | function main(){ 9 | fs.readdir(dir, function(err, files){ 10 | var sprites = []; 11 | if (err) throw err; 12 | files.forEach(function(filename){ 13 | if(filename.indexOf('hero14') === -1) return; 14 | var file = fs.readFileSync(dir+'/'+filename, 'utf-8'); 15 | var rawSprite = file.replace(/\r\n/g, '\n'); 16 | var indexOfAnimation = rawSprite.indexOf('\nAnimation:\n'); 17 | var frames = rawSprite.substring(0, indexOfAnimation).split('//new Frame'); 18 | var animations = rawSprite.substring(indexOfAnimation+12).split(','); 19 | 20 | var newFile = ''; 21 | for (var i = 0; i < frames.length; i++) { 22 | var lines = frames[i].split('\n'); 23 | for (var j = 0; j < lines.length; j++) { 24 | lines[j] = lines[j].split('').reverse().join(''); 25 | } 26 | frames[i] = lines.join('\n'); 27 | } 28 | frames = frames.join('//new Frame'); 29 | newFile = frames + `\nAnimation:\n${animations}`; 30 | fs.writeFile('./assets/'+filename, newFile, function(err){ 31 | if(err){ 32 | console.log('exception saving file', err); 33 | } 34 | console.log(`file ${filename} replaced`) 35 | }) 36 | }); 37 | }); 38 | }; 39 | 40 | main(); -------------------------------------------------------------------------------- /src/collisionHandler.js: -------------------------------------------------------------------------------- 1 | 2 | // first two sprites collides when overlaps 3 | 4 | var itemsColliders = {}; 5 | var matrixDrawing = {}; 6 | 7 | function addHitPixelToCollisionMatrix(x, y, id, target) { 8 | var key = x+'-'+y; 9 | if(!matrixDrawing[key]) matrixDrawing[key] = []; 10 | matrixDrawing[key][0] = [id, target]; 11 | } 12 | 13 | function addPixelToCollisionMatrix(x, y, id, type) { 14 | var key = x+'-'+y; 15 | if(!matrixDrawing[key]) return; 16 | matrixDrawing[key].push([id, type]); 17 | 18 | var spriteHitId = matrixDrawing[key][0]; 19 | for (var i = 1; i < matrixDrawing[key].length; i++) { 20 | var data = matrixDrawing[key][i]; 21 | // if the same sprite is on the hit area continue 22 | if((spriteHitId[1]&data[1]) == 0) continue; 23 | if((spriteHitId[0]==data[0])) continue; 24 | var sprite = itemsColliders[data[0]]; 25 | var kicker = itemsColliders[spriteHitId[0]]; 26 | 27 | if(kicker.type==='pickable'){ 28 | return sprite.pick(kicker); 29 | } 30 | if(!kicker.damage(sprite, y)) return; 31 | if(player.id === sprite.id) { 32 | flash('#60004b'); 33 | } 34 | //sprite.colliding = true; 35 | // example 36 | var explosion = Sprite([x-8, y-8, 29, '#fff']); 37 | explosion.pixelSize = 2; 38 | explosion.orientation = 0; 39 | explosion.animationEnds = function(){ 40 | mainScene.remove(this); 41 | } 42 | mainScene.add(explosion); 43 | // ends example 44 | } 45 | 46 | } 47 | 48 | function resetMatrix() { 49 | matrixDrawing = {}; 50 | } 51 | -------------------------------------------------------------------------------- /src/items.js: -------------------------------------------------------------------------------- 1 | 2 | function Pickable(props) { 3 | var base = Sprite([props[0], props[1], 30]); 4 | base.frame = base.animation[props[2]]; 5 | base.pixelSize = 1; 6 | base.color = '#9bbc0f'; 7 | base.type = 'pickable'; 8 | base.colliding = false; 9 | base.collisionAnimation = collisionAnimations[30]; 10 | base.collisionFrame = base.collisionAnimation[props[2]]; 11 | base.targetHit = 3; 12 | var extended = { 13 | updateFrame: function(dt){}, 14 | setHitArea: function() { 15 | addHitPixelToCollisionMatrix(this.x, this.y, this.id, this.targetHit); 16 | addHitPixelToCollisionMatrix(this.x+4, this.y+4, this.id, this.targetHit); 17 | addHitPixelToCollisionMatrix(this.x+8, this.y-4, this.id, this.targetHit); 18 | addHitPixelToCollisionMatrix(this.x+12, this.y+4, this.id, this.targetHit); 19 | addHitPixelToCollisionMatrix(this.x+16, this.y-4, this.id, this.targetHit); 20 | }, 21 | update: function(dt) { 22 | this.collided = this.colliding; 23 | this.setHitArea(); 24 | } 25 | }; 26 | extendFunction(base, extended); 27 | return extended; 28 | } 29 | 30 | function Heart(props) { 31 | var base = Pickable([props[0], props[1], 6]); 32 | var extended = { 33 | affectFighter: function(fighter) { 34 | fighter.incrementHp(15); 35 | play(powerup); 36 | } 37 | }; 38 | extendFunction(base, extended); 39 | return extended; 40 | } 41 | 42 | function Disquette(props) { 43 | var base = Pickable([props[0], props[1], 7]); 44 | var extended = { 45 | affectFighter: function(fighter) { 46 | //fighter.incrementHp(15); 47 | play(powerup); 48 | mainScene.displayLevelUpScene() 49 | } 50 | }; 51 | extendFunction(base, extended); 52 | return extended; 53 | } 54 | -------------------------------------------------------------------------------- /sprite.temp: -------------------------------------------------------------------------------- 1 | 2 | ________________ 3 | _______MM_______ 4 | _______MM_______ 5 | _______MM_______ 6 | _____MMMM__M____ 7 | ____M_MMMM_M____ 8 | ___M__MMMM_M____ 9 | ___M__MMM_M_____ 10 | _______M________ 11 | ______MMM_______ 12 | ______M_MMM_____ 13 | ______M____M____ 14 | _____M_____M____ 15 | _____M____M_____ 16 | ____M___________ 17 | ____M___________ 18 | //new Frame 19 | ________________ 20 | _______MM_______ 21 | _______MM_______ 22 | _______MM_______ 23 | ______MMMM______ 24 | ______MMMM______ 25 | _____M_MM_M_____ 26 | _____M_MM_M_____ 27 | _____M____M_____ 28 | _____M_MM_M_____ 29 | ______M__M______ 30 | ______M__M______ 31 | ________________ 32 | ______M__M______ 33 | ______M__M______ 34 | ______M__M______ 35 | //new Frame 36 | ________________ 37 | ________________ 38 | ________________ 39 | ________________ 40 | _______MM_______ 41 | _______MM_______ 42 | ______MMMM______ 43 | _____MMMMMM_____ 44 | ____M__MM__M____ 45 | ___M___MM___M___ 46 | _______MM_______ 47 | ______M__M______ 48 | _____MM__MM_____ 49 | ____M______M____ 50 | _____MM__MM_____ 51 | ______M__M______ 52 | //new Frame 53 | ________________ 54 | ________________ 55 | ________________ 56 | ________________ 57 | ________MM______ 58 | ________MM______ 59 | _______MM_______ 60 | ______MMM_______ 61 | _____M_MM_M_____ 62 | ____M__MMM______ 63 | _______MM_______ 64 | _______M_M______ 65 | _______M__M_____ 66 | ______M___M_____ 67 | _____M____M_____ 68 | ____M_____M_____ 69 | //new Frame 70 | ________________ 71 | ________________ 72 | ___MM___________ 73 | __MMM___________ 74 | _MMM____________ 75 | _MMMM___________ 76 | __MM_MM_________ 77 | __MM____________ 78 | __MMMMMMMMMM____ 79 | __M_____________ 80 | ___MMMM_________ 81 | ________________ 82 | ________________ 83 | ________________ 84 | ________________ 85 | ________________ 86 | Animation: 87 | 0,1,2,3,4 -------------------------------------------------------------------------------- /lib/stats.min.js: -------------------------------------------------------------------------------- 1 | // stats.js - http://github.com/mrdoob/stats.js 2 | var Stats=function(){function h(a){c.appendChild(a.dom);return a}function k(a){for(var d=0;de+1E3&&(r.update(1E3*a/(c-e),100),e=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){g=this.end()},domElement:c,setMode:k}}; 4 | Stats.Panel=function(h,k,l){var c=Infinity,g=0,e=Math.round,a=e(window.devicePixelRatio||1),r=80*a,f=48*a,t=3*a,u=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=f;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,f);b.fillStyle=k;b.fillText(h,t,u);b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(f, 5 | v){c=Math.min(c,f);g=Math.max(g,f);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=k;b.fillText(e(f)+" "+h+" ("+e(c)+"-"+e(g)+")",t,u);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,e((1-f/v)*p))}}};"object"===typeof module&&(module.exports=Stats); 6 | -------------------------------------------------------------------------------- /assets/z_explosion_02.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | ________________ 6 | ________________ 7 | ________________ 8 | ________________ 9 | ________________ 10 | ________________ 11 | ________________ 12 | ________________ 13 | ________________ 14 | ________________ 15 | ________________ 16 | ________________ 17 | //new Frame 18 | ________________ 19 | ________________ 20 | ________________ 21 | ________________ 22 | ________________ 23 | ________________ 24 | _______M________ 25 | ____M__M__M_____ 26 | _____M___M______ 27 | ________________ 28 | ______M_M_______ 29 | _____M___M______ 30 | ________________ 31 | ________________ 32 | ________________ 33 | ________________ 34 | //new Frame 35 | ________________ 36 | ________________ 37 | ________________ 38 | ________________ 39 | _______M________ 40 | _______M________ 41 | ___MM______M____ 42 | ____M_____M_____ 43 | _______M________ 44 | ______MMM_______ 45 | _______M________ 46 | _____M___M______ 47 | ____M____M______ 48 | __________M_____ 49 | ________________ 50 | ________________ 51 | //new Frame 52 | ________________ 53 | ________________ 54 | ________________ 55 | _______M________ 56 | ___M___M________ 57 | ___M________M___ 58 | ____M______M____ 59 | _______M________ 60 | ______M_M_______ 61 | ___M_M___M_M____ 62 | ______M_M_______ 63 | _______M________ 64 | ____M___________ 65 | ___M___M__M_____ 66 | _______M___M____ 67 | ________________ 68 | //new Frame 69 | ________________ 70 | ________________ 71 | _______M________ 72 | __M____M________ 73 | ___M_________M__ 74 | ____________M___ 75 | ________________ 76 | ______M_M_______ 77 | _____M___M______ 78 | _M___________M__ 79 | _____M___M______ 80 | ______M_M_______ 81 | ________________ 82 | ___M____________ 83 | __M____M___M____ 84 | ____________M___ 85 | Animation: 86 | 0,1,3,4,0,0,0,0,0,0,0 -------------------------------------------------------------------------------- /src/levelUpScene.js: -------------------------------------------------------------------------------- 1 | // second scene HUD 2 | var levelUpScene = Scene({}); 3 | levelUpScene.active = false; 4 | 5 | levelUpScene.create = function() { 6 | 7 | var name = Text([40, 28, 'n30: tank, load a new program: ']); 8 | this.add(name); 9 | 10 | this.options = []; 11 | 12 | this.indexOption = 0; 13 | this.options.push(Text([55, 50, 'hit points: '+basePlayerStat.maxHp+' (+5)'])); 14 | this.options.push(Text([55, 65, 'defense: +'+basePlayerStat.defense+' (+0.5)'])); 15 | this.options.push(Text([55, 80, 'damage: +'+basePlayerStat.damage+' (+0.5)'])); 16 | 17 | for (var i = 0; i < this.options.length; i++) { 18 | this.add(this.options[i]); 19 | } 20 | 21 | this.setOption(0); 22 | }; 23 | 24 | levelUpScene.setOption = function(index){ 25 | this.options[this.indexOption].color = '#ddfed9'; 26 | this.indexOption = index; 27 | if(this.indexOption>=this.options.length){ 28 | this.indexOption = 0; 29 | } 30 | if(this.indexOption<0){ 31 | this.indexOption = this.options.length - 1; 32 | } 33 | this.options[this.indexOption].color = '#9bbc0f'; 34 | } 35 | 36 | levelUpScene.applyStat = function(){ 37 | switch(this.indexOption){ 38 | case 0: basePlayerStat.maxHp+=5;break; 39 | case 1: basePlayerStat.defense+=0.5;break; 40 | case 2: basePlayerStat.damage+=0.5;break; 41 | } 42 | this.options[0].setText('hit points: '+basePlayerStat.maxHp+' (+5)'); 43 | this.options[1].setText('defense: +'+basePlayerStat.defense+' (+0.5)'); 44 | this.options[2].setText('damage: +'+basePlayerStat.damage+' (+0.5)'); 45 | 46 | player.resetHp(); 47 | play(powerup); 48 | } 49 | 50 | levelUpScene.updateData = function(time){ 51 | } 52 | 53 | levelUpScene.predraw = function() { 54 | if(!this.active) return; 55 | graphics.fillStyle = 'rgba(0,0,0,0.5)'; 56 | graphics.fillRect(0,0,320,240); 57 | } 58 | 59 | 60 | sceneManager.add(levelUpScene); 61 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js13k2018", 3 | "version": "0.0.1", 4 | "description": "my entry for the #js13k 2018", 5 | "main": "index.js", 6 | "scripts": { 7 | "concat": "./scripts/concat.sh > dist/build.js && cp dist/build.js target/b.js", 8 | "clean": "rm target.zip; rm -rf dist/; rm -rf target/; mkdir -p dist target", 9 | "compileglsl": "./scripts/compileglsfiles.sh src/shaders dist", 10 | "minify": "npx google-closure-compiler --compilation_level=ADVANCED_OPTIMIZATIONS --js=dist/build.js --js_output_file=dist/build.min.js", 11 | "gen": "cp src/index.html target/index.html && cp dist/build.min.js target/b.js", 12 | "zip": "cd target; zip -r ../target.zip .; cd ..; wc -c target.zip", 13 | "nominify": "cp dist/build.js dist/build.min.js", 14 | "build-nominify": "npm run clean && npm run compileglsl && npm run concat && npm run nominify && npm run gen", 15 | "build-nominify-purejs": "npm run clean && npm run concat && npm run nominify && npm run gen", 16 | "build": "export NODE_ENV=production; npm run clean && npm run compileglsl && npm run concat && npm run minify && npm run gen && npm run zip", 17 | "watch": "nodemon -e js,sh --watch src --watch scripts --exec npm run build-nominify;", 18 | "liveserver": "mkdir -p target; cd target; live-server --no-browser", 19 | "start": "npm run watch & npm run liveserver", 20 | 21 | "build-sprites": "node ./spriteConverter.js", 22 | 23 | "concatlite": "./scripts/concat.sh > dist/build.js && cp dist/build.js target/b.js", 24 | "watchlite": "nodemon -e js,sh,html --watch src --watch scripts --exec npm run concatlite", 25 | "lite": "npm run watchlite & npm run liveserver" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "git+https://github.com/agar3s/js13k2018.git" 30 | }, 31 | "keywords": [ 32 | "js13k" 33 | ], 34 | "author": "agar3s", 35 | "license": "ISC", 36 | "bugs": { 37 | "url": "https://github.com/agar3s/js13k2018/issues" 38 | }, 39 | "homepage": "https://github.com/agar3s/js13k2018#readme", 40 | "devDependencies": { 41 | "glslmin": "0.0.0", 42 | "live-server": "^1.2.0", 43 | "nodemon": "^1.18.3" 44 | }, 45 | "dependencies": { 46 | "google-closure-compiler": "^20180805.0.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /assets/z_explosion_01.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | _____MM___MM____ 6 | ____MMMM_MMMM___ 7 | _____MMMMMMMM___ 8 | _____MMMMMMM____ 9 | _____MMMMMMMMM_M 10 | _____MMMMMMM____ 11 | _____MMMMMMMM___ 12 | ____MMMMMMMMM___ 13 | ____MMMMM_MM____ 14 | _____MM_________ 15 | ________________ 16 | ________________ 17 | //new Frame 18 | ________________ 19 | ________________ 20 | ________________ 21 | _____MM__MM_____ 22 | ____MMMM__MM____ 23 | _____MM_________ 24 | _________M_MM___ 25 | ____MM__MMM_____ 26 | ___MMMM_MM______ 27 | ___MMMM__M__MM__ 28 | _______MMMM_____ 29 | _____MM_MM______ 30 | ____MMMM________ 31 | _____MM__MM_____ 32 | ________MMMM____ 33 | ________________ 34 | //new Frame 35 | ________________ 36 | ________________ 37 | ___MM___MM______ 38 | __M_MM___MM_____ 39 | __M_________M___ 40 | _____MM_________ 41 | ______MM_MM_____ 42 | __MM_____MM_____ 43 | _MMMM_MM________ 44 | _MMMM____M______ 45 | __MM__MM________ 46 | ______MM_MM_____ 47 | __MM_MM__MM_____ 48 | ________________ 49 | ___MM___MM_M____ 50 | __MM____M_______ 51 | //new Frame 52 | ________________ 53 | __MM____MM______ 54 | ___MM___MM______ 55 | ________________ 56 | ____MM____M_____ 57 | ____MM__________ 58 | ________M_______ 59 | ____MM__________ 60 | _MM_MM__________ 61 | _MM______M______ 62 | _______M________ 63 | ________________ 64 | _________M______ 65 | _______MM__M____ 66 | __MM___MM_______ 67 | __MM______M_____ 68 | //new Frame 69 | ________________ 70 | __M_____M_______ 71 | ________________ 72 | ________________ 73 | ____M___________ 74 | ________________ 75 | ________________ 76 | ________________ 77 | _M__M___________ 78 | ________________ 79 | ________________ 80 | ________________ 81 | ________________ 82 | ________________ 83 | _______M________ 84 | __M_____________ 85 | //new Frame 86 | ________________ 87 | ________________ 88 | ________________ 89 | ________________ 90 | ________________ 91 | ________________ 92 | ________________ 93 | ________________ 94 | ________________ 95 | ________________ 96 | ________________ 97 | ________________ 98 | ________________ 99 | ________________ 100 | ________________ 101 | ________________ 102 | Animation: 103 | 5,0,1,2,2,3,3,4,4,5 -------------------------------------------------------------------------------- /src/spriteLoader.js: -------------------------------------------------------------------------------- 1 | 2 | var collisionAnimations = []; 3 | var conter = 0; 4 | function animationLoader (animationData) { 5 | var frames = []; 6 | var previousFrame = []; 7 | var frame = []; 8 | 9 | var indexCollider = 0; 10 | for (var i = 0; i < animationData.length; i+=2) { 11 | var dataByte = parseInt(animationData[i]+animationData[i+1], 16); 12 | if (dataByte==2) { 13 | indexCollider = i+2; 14 | break; 15 | } 16 | if (dataByte==1) { 17 | frames.push(JSON.parse(JSON.stringify(frame))); 18 | previousFrame = frame; 19 | } else { 20 | var index = previousFrame.indexOf(dataByte); 21 | if(index==-1){ 22 | frame.push(dataByte); 23 | } else { 24 | index = frame.indexOf(dataByte); 25 | frame.splice(index, 1); 26 | } 27 | } 28 | } 29 | frames.push(frame); 30 | // check frames with collisions 31 | 32 | var indexFrame = 0; 33 | previousFrame = []; 34 | frame = []; 35 | var colliderFrames = []; 36 | for (var i = indexCollider; i < animationData.length; i+=2) { 37 | var dataByte = parseInt(animationData[i]+animationData[i+1], 16); 38 | if (dataByte==1) { 39 | colliderFrames.push(JSON.parse(JSON.stringify(frame))); 40 | previousFrame = frame; 41 | } else { 42 | var index = previousFrame.indexOf(dataByte); 43 | if(index==-1){ 44 | frame.push(dataByte); 45 | } else { 46 | index = frame.indexOf(dataByte); 47 | frame.splice(index, 1); 48 | } 49 | } 50 | } 51 | colliderFrames.push(frame); 52 | 53 | 54 | 55 | for (var i = 0; i < frames.length; i++) { 56 | for (var j = 0; j < frames[i].length; j++) { 57 | var dataByte = frames[i][j]; 58 | var x = dataByte&0x0f; 59 | var y = dataByte>>4; 60 | frames[i][j] = [x, y]; 61 | } 62 | } 63 | 64 | for (var i = 0; i < colliderFrames.length; i++) { 65 | for (var j = 0; j < colliderFrames[i].length; j++) { 66 | var dataByte = colliderFrames[i][j]; 67 | var x = dataByte&0x0f; 68 | var y = dataByte>>4; 69 | frames[i].push([x, y, 1]); 70 | } 71 | } 72 | 73 | return frames; 74 | } 75 | 76 | for (var i = 0; i < animations.length; i++) { 77 | animations[i] = animationLoader(animations[i]); 78 | collisionAnimations.push([]) 79 | 80 | // frames 81 | for (var j = 0; j < animations[i].length; j++) { 82 | // frame 83 | collisionAnimations[i].push([]) 84 | for (var k = 0; k < animations[i][j].length; k++) { 85 | var coords = animations[i][j][k]; 86 | if(coords[2]==1) collisionAnimations[i][j].push([coords[0], coords[1]]) 87 | } 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /lib/webgl.js: -------------------------------------------------------------------------------- 1 | /* 2 | * original script from @gre 3 | * https://github.com/gre/behind-asteroids/blob/master/src/lib/webgl.sh 4 | */ 5 | function glCreateShader (vert, frag) { 6 | var handle, type = gl.VERTEX_SHADER, src = vert; 7 | handle = gl.createShader(type); 8 | gl.shaderSource(handle, src); 9 | gl.compileShader(handle); 10 | var vertex = handle; 11 | if (DEBUG) { 12 | if (!gl.getShaderParameter(handle, gl.COMPILE_STATUS)) 13 | throw gl.getShaderInfoLog(handle); 14 | } 15 | 16 | type = gl.FRAGMENT_SHADER; 17 | src = frag; 18 | handle = gl.createShader(type); 19 | gl.shaderSource(handle, src); 20 | gl.compileShader(handle); 21 | var fragment = handle; 22 | 23 | if (DEBUG) { 24 | if (!gl.getShaderParameter(handle, gl.COMPILE_STATUS)) 25 | throw gl.getShaderInfoLog(handle); 26 | } 27 | 28 | var program = gl.createProgram(); 29 | gl.attachShader(program, vertex); 30 | gl.attachShader(program, fragment); 31 | gl.linkProgram(program); 32 | 33 | if (DEBUG) { 34 | if (!gl.getProgramParameter(program, gl.LINK_STATUS)) 35 | throw gl.getProgramInfoLog(program); 36 | } 37 | 38 | gl.useProgram(program); 39 | var p = gl.getAttribLocation(program, "p"); 40 | gl.enableVertexAttribArray(p); 41 | gl.vertexAttribPointer(p, 2, gl.FLOAT, false, 0, 0); 42 | return [program]; 43 | } 44 | function glBindShader (shader) { 45 | gl.useProgram(shader[0]); 46 | } 47 | function glUniformLocation(shader, name) { 48 | return shader[name] || (shader[name] = gl.getUniformLocation(shader[0], name)); 49 | } 50 | function glCreateTexture () { 51 | var tex = gl.createTexture(); 52 | gl.bindTexture(gl.TEXTURE_2D, tex); 53 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 54 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 55 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 56 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 57 | return tex; 58 | } 59 | function glSetTexture (t, value) { 60 | gl.bindTexture(gl.TEXTURE_2D, t); 61 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, value); 62 | } 63 | function glBindTexture (t, unit) { 64 | gl.activeTexture(gl.TEXTURE0 + unit); 65 | gl.bindTexture(gl.TEXTURE_2D, t); 66 | return unit; 67 | } 68 | function glCreateFBO () { 69 | var handle = gl.createFramebuffer(); 70 | gl.bindFramebuffer(gl.FRAMEBUFFER, handle); 71 | var color = glCreateTexture(); 72 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, W, H, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 73 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, color, 0); 74 | return [handle, color]; 75 | } 76 | function glBindFBO (fbo) { 77 | gl.bindFramebuffer(gl.FRAMEBUFFER, fbo[0]); 78 | } 79 | function glGetFBOTexture (fbo) { 80 | return fbo[1]; 81 | } 82 | -------------------------------------------------------------------------------- /src/scene.js: -------------------------------------------------------------------------------- 1 | // src/scene.js 2 | // should display different objects in screen, like scenes in phaser 3 | 4 | var sceneManager = { 5 | scenes: [], 6 | add: function(scene) { 7 | scene.create(); 8 | this.scenes.push(scene); 9 | }, 10 | update: function(time, dt) { 11 | for (var i = 0; i < this.scenes.length; i++) { 12 | this.scenes[i].update(time, dt); 13 | } 14 | }, 15 | draw: function() { 16 | for (var i = 0; i < this.scenes.length; i++) { 17 | this.scenes[i].predraw(); 18 | this.scenes[i].draw(); 19 | } 20 | } 21 | }; 22 | 23 | function Scene (props) { 24 | var t = { 25 | x: 0, 26 | dx: 0, 27 | active: true, 28 | children: [], 29 | following: undefined, 30 | limit: [], 31 | maxWidth: 320, 32 | create: function(){}, 33 | add: function(gameObject) { 34 | t.children.push(gameObject); 35 | if(gameObject.type==='character'||gameObject.type==='pickable'){ 36 | itemsColliders[gameObject.id] = gameObject; 37 | } 38 | }, 39 | remove: function(gameObject) { 40 | var index = t.children.indexOf(gameObject); 41 | if(index!=-1){ 42 | t.children.splice(index, 1); 43 | } 44 | }, 45 | updateData: function(time, dt){}, 46 | update: function(time, dt) { 47 | if(!t.active) return; 48 | for (var i = 0; i < t.children.length; i++) { 49 | var gameObject = t.children[i] 50 | if(gameObject.x + 24 > -this.x && gameObject.x < -this.x + 320){ 51 | gameObject.update(dt); 52 | } 53 | } 54 | t.updateData(time, dt); 55 | 56 | if (this.moving) { 57 | this.moving = this.x>-this.targetX && this.x-320>-this.limit[1]; 58 | if (this.moving) this.x -= 1; 59 | }else if(this.following) { 60 | this.x = -(this.following.x-150); 61 | this.x = ~~this.x; 62 | if(this.x>-this.limit[0]) { 63 | this.x = -this.limit[0]; 64 | }else if(this.x<-this.limit[1]+320){ 65 | this.x = -this.limit[1]+320; 66 | } 67 | } 68 | }, 69 | predraw: function(){}, 70 | draw: function() { 71 | if(!t.active) return; 72 | graphics.save(); 73 | graphics.translate(this.x, 0); 74 | 75 | for (var i = 0; i < t.children.length; i++) { 76 | var gameObject = t.children[i] 77 | if(gameObject.x + 24 > -this.x && gameObject.x < -this.x + 310 && gameObject.visible){ 78 | gameObject.draw(); 79 | } 80 | } 81 | 82 | graphics.restore(); 83 | }, 84 | moveToLimit: function(minLimit, maxLimit){ 85 | this.moving = true; 86 | this.targetX = player.x-150; 87 | if (this.targetX> 2 | 3 | function GameObject(props) { 4 | return { 5 | x: props[0], 6 | y: props[1], 7 | visible: true, 8 | update: function(dt) {}, 9 | draw: function() {} 10 | } 11 | } 12 | 13 | function Sprite(props) { 14 | var base = GameObject(props); 15 | 16 | var extended = { 17 | dx: base.x, 18 | dy: base.y, 19 | id: (~~(Math.random()*10000000)).toString(16), 20 | frame: [], 21 | type: 'sprite', 22 | animation: animations[props[2]], 23 | color: props[3], 24 | animIndex: 0, 25 | pixelSize: 4, 26 | orientation: 1, // right 27 | animationEnds: function() {}, 28 | updateFrame: function (dt) { 29 | this.animIndex += dt*22; 30 | if (this.animIndex >= this.animation.length) { 31 | this.animIndex = 0; 32 | this.animationEnds(); 33 | } 34 | this.frame = this.animation[~~(this.animIndex)]; 35 | }, 36 | updateData: function(dt) {}, 37 | update: function(dt) { 38 | this.updateData(dt); 39 | this.updateFrame(dt); 40 | }, 41 | drawFrame: function() { 42 | for (var i = 0; i < this.frame.length; i++) { 43 | var coords = this.frame[i]; 44 | graphics.fillStyle = this.color 45 | if(this.orientation == 1){ 46 | graphics.fillRect(coords[0]*this.pixelSize, coords[1]*this.pixelSize, this.pixelSize, this.pixelSize); 47 | }else{ 48 | graphics.fillRect(14*this.pixelSize - coords[0]*this.pixelSize, coords[1]*this.pixelSize, this.pixelSize, this.pixelSize); 49 | } 50 | } 51 | }, 52 | draw: function() { 53 | graphics.save(); 54 | graphics.translate(this.x, this.y); 55 | graphics.fillStyle = this.color; 56 | this.drawFrame(); 57 | graphics.restore(); 58 | }, 59 | setAnimation: function(animationIndex) { 60 | this.animation = animations[animationIndex] 61 | } 62 | } 63 | extendFunction(base, extended); 64 | return extended; 65 | } 66 | 67 | 68 | function Character(props) { 69 | var base = Sprite(props); 70 | var extended = { 71 | type: 'character', 72 | colliding: false, 73 | hitPoints: 30, 74 | collisionAnimation: collisionAnimations[props[2]], 75 | collisionFrame: [], 76 | targetHit: 2, 77 | typeHit: 1, 78 | update: function(dt) { 79 | this.collided = this.colliding; 80 | this.updateData(dt); 81 | this.updateFrame(dt); 82 | this.collisionFrame = this.collisionAnimation[~~(this.animIndex)]; 83 | this.setHitArea(); 84 | }, 85 | setHitArea: function() { 86 | for (var i = 0; i < this.collisionFrame.length; i++) { 87 | var coords = this.collisionFrame[i]; 88 | if(this.orientation == 1){ 89 | addHitPixelToCollisionMatrix(this.x + coords[0]*this.pixelSize, this.y +coords[1]*this.pixelSize, this.id, this.targetHit); 90 | }else{ 91 | addHitPixelToCollisionMatrix(this.x + 14*this.pixelSize - coords[0]*this.pixelSize, this.y +coords[1]*this.pixelSize, this.id, this.targetHit); 92 | } 93 | } 94 | } 95 | } 96 | extendFunction(base, extended) 97 | return extended 98 | } 99 | -------------------------------------------------------------------------------- /src/gameHud.js: -------------------------------------------------------------------------------- 1 | // second scene HUD 2 | var hudScene = Scene({}); 3 | var enemyPunched; 4 | var enemyId = Text([250, 28, '']); 5 | 6 | hudScene.create = function() { 7 | var heroBar = GameObject([20,20]); 8 | heroBar.barLength = 80; 9 | heroBar.draw = function() { 10 | graphics.fillStyle = '#DFEFE2'; 11 | var length = 80*(player.hitPoints/30); 12 | if(length<0) return; 13 | graphics.fillRect(this.x, this.y, ~~length, 5); 14 | } 15 | heroBar.direction = 1; 16 | heroBar.update = function(dt) {} 17 | this.add(heroBar); 18 | 19 | var enemyBar = GameObject([300,20]); 20 | enemyBar.barLength = 80; 21 | enemyBar.draw = function() { 22 | if (enemyPunched){ 23 | graphics.fillStyle = enemyPunched.color; 24 | var length = ~~(80*(enemyPunched.hitPoints/30)); 25 | if(length<0) return; 26 | var start = this.x - length 27 | graphics.fillRect(start, this.y, length, 5); 28 | } 29 | } 30 | enemyBar.direction = 1; 31 | enemyBar.update = function(dt) {} 32 | 33 | this.add(heroBar); 34 | var name = Text([20, 28, 'mr anderson']); 35 | name.size = 1; 36 | this.add(name); 37 | this.add(enemyBar); 38 | this.add(enemyId); 39 | 40 | var progressBar = GameObject([20, 234]); 41 | progressBar.length = 280; 42 | progressBar.draw = function() { 43 | graphics.fillStyle = '#306230'; 44 | graphics.fillRect(this.x, this.y, this.length, 3); 45 | graphics.fillStyle = '#9bbc0f'; 46 | var position = ~~(this.length*((player.x+12)/(mainScene.maxWidth-24))); 47 | graphics.fillRect(this.x + position, this.y, 3, 3); 48 | } 49 | this.add(progressBar); 50 | 51 | this.goMessage = Text([200, 60, 'go!']); 52 | this.goMessage.size = 2; 53 | this.goMessage.time = 0; 54 | this.goMessage.color = '#9bbc0f'; 55 | this.goMessage.visible = false; 56 | this.goMessage.update = function(dt) { 57 | if(!this.active) return; 58 | this.time += dt; 59 | var value = this.time%0.8; 60 | this.visible = value<0.6; 61 | 62 | if(this.time > 4) { 63 | this.visible = false; 64 | this.time = 0; 65 | this.active = false; 66 | } 67 | } 68 | 69 | this.add(this.goMessage); 70 | 71 | this.clock = Text([150, 1, '00:00']) 72 | this.clock.time = 0; 73 | this.clock.setTime = function(time){ 74 | this.time = time; 75 | var cents = this.time%100; 76 | if(cents<10) cents = '0'+cents; 77 | var seconds = ~~(this.time/100); 78 | if(seconds<10) seconds = '0'+seconds; 79 | this.setText(seconds+':'+cents); 80 | } 81 | this.add(this.clock); 82 | 83 | this.dialogue = Text([10, 70, '']); 84 | this.dialogue.size = 1; 85 | this.dialogue.time = 0; 86 | this.dialogue.visible = false; 87 | this.dialogue.pipeline = []; 88 | this.dialogue.index = -1; 89 | this.dialogue.color = '#9bbc0f'; 90 | this.dialogue.setIndex = function(index){ 91 | this.index = index; 92 | if(this.index>=this.pipeline.length) { 93 | this.active = false; 94 | this.visible = false; 95 | return; 96 | } 97 | var dialogue = this.pipeline[this.index]; 98 | this.setText(dialogue[0]); 99 | this.time = dialogue[1]; 100 | this.active = true; 101 | this.visible = true; 102 | 103 | }; 104 | this.dialogue.update = function(dt) { 105 | if(!this.active) return; 106 | this.time -= dt; 107 | if(this.time<0) { 108 | this.setIndex(this.index + 1); 109 | } 110 | } 111 | this.add(this.dialogue); 112 | }; 113 | 114 | hudScene.updateData = function(time){ 115 | var time = ~~(time/10); 116 | if(this.clock.time != time){ 117 | this.clock.setTime(time); 118 | } 119 | } 120 | 121 | hudScene.setDialoguePipeline = function(dialogue){ 122 | this.dialogue.pipeline = dialogue; 123 | if(this.dialogue.pipeline.length>0){ 124 | this.dialogue.setIndex(0); 125 | } 126 | } 127 | 128 | 129 | sceneManager.add(hudScene); 130 | 131 | -------------------------------------------------------------------------------- /src/theScript.js: -------------------------------------------------------------------------------- 1 | 2 | var matrixScript = [ 3 | // 0 4 | [['tank: operator', 2], 5 | ['',0.6], 6 | ['neo: tank, i need an exit', 2], 7 | ['',0.6], 8 | ['neo: now!',2], 9 | ['',1], 10 | ['operator: .', 0.4], 11 | ['operator: ..', 0.4], 12 | ['operator: ...', 1], 13 | ['operator: got one ready', 2], 14 | ['', 0.6], 15 | ['operator: subway station, state and balboa.', 2] 16 | ], 17 | // 1 18 | [['...', 0.2], 19 | ['agent smith: mr. anderson', 2], 20 | ['',0.6], 21 | ['agent smith: we meet again', 2], 22 | ['',2], 23 | ['trinity: run, neo. run! what is he doing?', 3], 24 | ['',0.6], 25 | ['morpheus: he’s beginning to believe.', 2] 26 | ], 27 | // 2 28 | [['agent smith: i’m going to enjoy...', 1.5], 29 | ['agent smith: watching you die,', 1.5], 30 | ['agent smith: mr. anderson.', 1.5], 31 | ['',0.6], 32 | ['neo: my name is..', 1.2], 33 | ['',0.6], 34 | ['neo: n', 0.4], 35 | ['neo: ne', 0.4], 36 | ['neo: neo', 0.4], 37 | ['neo: neo!', 0.2], 38 | ['neo: neo!!', 0.2], 39 | ['neo: neo!!!', 0.2], 40 | ['neo: neo!!!!', 1] 41 | ], 42 | // 3 43 | [['neo: mr. wizard...', 2], 44 | ['neo: get me the hell out of here.', 3], 45 | ['',0.6], 46 | ['tank: got a patch on an old exit...', 2], 47 | ['tank: wabash and lake.', 2] 48 | ], 49 | // 4 50 | [['',0.6], 51 | ['.',0.6], 52 | ['..',0.6], 53 | ['...',1], 54 | ['',1], 55 | ['neo: oh shit...', 1.5], 56 | ['neo: help.', 1.5], 57 | ['neo: need a little help.', 1.5] 58 | ], 59 | //5 60 | [['',0.6], 61 | ['agent smith: i’m going to be honest', 3], 62 | ['agent smith: i hate this place,', 3], 63 | ['',0.6], 64 | ['agent smith: this zoo', 2], 65 | ['agent smith: this prison', 2], 66 | ['agent smith: this reality', 2], 67 | ['agent smith: whatever you want to call it', 3], 68 | ['agent smith: i can’t stand it any longer.', 3], 69 | ['',1], 70 | ['agent smith: it’s the smell', 3], 71 | ['agent smith: if there is such a thing', 3], 72 | ['agent smith: i feel.', 0.6], 73 | ['agent smith: i feel..', 0.6], 74 | ['agent smith: i feel...', 1.8], 75 | ['agent smith: saturated by it', 2], 76 | ['',0.6], 77 | ['agent smith: i can taste your stink', 2], 78 | ['agent smith: and every time i do', 2], 79 | ['agent smith: i feel i have somehow been...', 3], 80 | ['agent smith: infected by it', 2], 81 | ['agent smith: it’s repulsive', 2], 82 | ['agent smith: ', 2], 83 | ['agent smith: i must get out of here', 2] 84 | ], 85 | //6 86 | [['...',0.6], 87 | ['i know you’re out there.', 2], 88 | ['i can feel you now.',2], 89 | ['i know that you’re afraid.', 2], 90 | ['you’re afraid of us.', 2], 91 | ['you’re afraid of change.', 2], 92 | ['',0.6], 93 | ['i don’t know the future.', 2], 94 | ['i didn’t come here to tell you ', 2], 95 | ['how this is going to end.', 2], 96 | ['i came here to tell you how ', 2], 97 | ['it’s going to begin.', 2], 98 | ['',0.6], 99 | ['i’m going to hang up this phone', 2], 100 | ['and then i’m going to show these', 2], 101 | ['people what you don’t want', 2], 102 | ['them to see.', 2], 103 | ['',0.6], 104 | ['i’m going to show them a world without you,', 2], 105 | ['a world without rules and controls,', 2], 106 | ['without borders or boundaries,', 2], 107 | ['a world where anything is possible.', 2], 108 | ['where we go from there is a choice', 2], 109 | ['i leave to you', 2], 110 | ['',0.6], 111 | ['thanks for playing', 3], 112 | ['m', 0.05], 113 | ['ma', 0.05], 114 | ['mad', 0.05], 115 | ['made', 0.05], 116 | ['made ', 0.05], 117 | ['made w', 0.05], 118 | ['made wi', 0.05], 119 | ['made wit', 0.05], 120 | ['made with', 0.05], 121 | ['made with ', 0.05], 122 | ['made with l', 0.05], 123 | ['made with lo', 0.05], 124 | ['made with lov', 0.05], 125 | ['made with love', 0.05], 126 | ['made with love ', 0.05], 127 | ['made with love b', 0.05], 128 | ['made with love by', 0.05], 129 | ['made with love by ', 0.05], 130 | ['made with love by a', 0.05], 131 | ['made with love by ag', 0.05], 132 | ['made with love by aga', 0.05], 133 | ['made with love by agar', 0.05], 134 | ['made with love by agar3', 0.05], 135 | ['made with love by agar3s', 60] 136 | 137 | ] 138 | ]; 139 | -------------------------------------------------------------------------------- /spriteConverter.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var dir = './assets'; 3 | 4 | //assuming sprites with 16X16 dimmension 5 | var cols = 16; 6 | var rows = 16; 7 | 8 | function main(cb){ 9 | fs.readdir(dir, function(err, files){ 10 | var sprites = []; 11 | if (err) throw err; 12 | files.forEach(function(filename){ 13 | if(filename.indexOf('.sprite') === -1) return; 14 | var file = fs.readFileSync(dir+'/'+filename, 'utf-8'); 15 | var res = processFile(filename, file); 16 | sprites.push(res); 17 | }); 18 | 19 | var result = joinSprites(sprites); 20 | return cb(result); 21 | }); 22 | }; 23 | 24 | function copyArray(array){ 25 | var newArray = []; 26 | for (var i = 0; i < array.length; i++) { 27 | newArray.push(array[i]); 28 | }; 29 | return newArray; 30 | } 31 | 32 | function isEmptyLayer(sprite){ 33 | var sum = 0; 34 | for (var i = 0; i < sprite.frames.length; i++) { 35 | sum+=sprite.frames[i].length; 36 | }; 37 | return !sprite.key && !sum; 38 | } 39 | 40 | function processFile(name, rawSprite){ 41 | rawSprite = rawSprite.replace(/\r\n/g, '\n'); 42 | var indexOfAnimation = rawSprite.indexOf('\nAnimation:\n'); 43 | var frames = rawSprite.substring(0, indexOfAnimation).split('//new Frame'); 44 | var animations = rawSprite.substring(indexOfAnimation+12).split(','); 45 | 46 | return processSprite(name, copyArray(frames), animations); 47 | }; 48 | 49 | function saveSprite(name, byteArray){ 50 | fs.writeFile('./assets/'+name, byteArray.join(''), function (err){ 51 | if(err){ 52 | console.log('exception:', err); 53 | return; 54 | } 55 | console.log('file created'); 56 | }); 57 | 58 | } 59 | 60 | function processSprite(name, frames, animations){ 61 | for (var i = 0; i < frames.length; i++) { 62 | frames[i] = encodeFrame(frames[i]); 63 | }; 64 | console.log('processing ', name) 65 | var animres = buildDiffArray(frames, animations); 66 | 67 | var fullAnimation = []; 68 | animres.main.forEach(function(data){ 69 | fullAnimation = fullAnimation.concat([...data]).concat(['01']); 70 | }); 71 | fullAnimation.splice(fullAnimation.length-1, 1); 72 | fullAnimation = fullAnimation.concat(['02']) 73 | animres.collision.forEach(function(data){ 74 | fullAnimation = fullAnimation.concat([...data]).concat(['01']); 75 | }); 76 | fullAnimation.splice(fullAnimation.length-1, 1); 77 | 78 | return { 79 | name: name.replace('.sprite', ''), 80 | frames: fullAnimation 81 | }; 82 | } 83 | 84 | function encodeFrame(frame){ 85 | var mainFrameByteArray = []; 86 | var collisionFrameByteArray = []; 87 | var encoded = ''; 88 | var data = frame.replace(/\n/g, ''); 89 | for (var i = 0; i < data.length; i++) { 90 | var character = data[i]; 91 | if(character==='M' || character==='C'){ 92 | var x = (i%cols); 93 | var y = ~~(i/rows); 94 | //encode the value as an hexadecimal code 95 | // yx 96 | var code = ((y<<4)+x).toString(16); 97 | if(code.length==1) code = `0${code}` 98 | 99 | if(character==='M') { 100 | mainFrameByteArray.push(code); 101 | }else { 102 | collisionFrameByteArray.push(code); 103 | } 104 | } 105 | if(character==='/'){ 106 | break; 107 | } 108 | }; 109 | 110 | 111 | return { 112 | main: mainFrameByteArray, 113 | collision: collisionFrameByteArray 114 | } 115 | 116 | }; 117 | 118 | function buildDiffArray(encodedFrames, animations){ 119 | var diffMainArray = []; 120 | var diffCollisionArray = []; 121 | var arrangedMainFrames = []; 122 | var arrangedCollisionFrames = []; 123 | for (var i = 0; i < animations.length; i++) { 124 | arrangedMainFrames.push(encodedFrames[animations[i]].main); 125 | arrangedCollisionFrames.push(encodedFrames[animations[i]].collision); 126 | }; 127 | // starting frame 128 | diffMainArray.push(arrangedMainFrames[0]); 129 | diffCollisionArray.push(arrangedCollisionFrames[0]); 130 | for (var j = 1; j < arrangedMainFrames.length; j++) { 131 | var diffMainElement = []; 132 | var diffCollisionElement = []; 133 | for (var k = arrangedMainFrames[j].length - 1; k >= 0; k--) { 134 | if(arrangedMainFrames[j-1].indexOf(arrangedMainFrames[j][k])==-1){ 135 | diffMainElement.push(arrangedMainFrames[j][k]); 136 | } 137 | }; 138 | for (var k = arrangedMainFrames[j-1].length - 1; k >= 0; k--) { 139 | if(arrangedMainFrames[j].indexOf(arrangedMainFrames[j-1][k])==-1){ 140 | diffMainElement.push(arrangedMainFrames[j-1][k]); 141 | } 142 | }; 143 | // check collider frames 144 | for (var k = arrangedCollisionFrames[j].length - 1; k >= 0; k--) { 145 | if(arrangedCollisionFrames[j-1].indexOf(arrangedCollisionFrames[j][k])==-1){ 146 | diffCollisionElement.push(arrangedCollisionFrames[j][k]); 147 | } 148 | }; 149 | for (var k = arrangedCollisionFrames[j-1].length - 1; k >= 0; k--) { 150 | if(arrangedCollisionFrames[j].indexOf(arrangedCollisionFrames[j-1][k])==-1){ 151 | diffCollisionElement.push(arrangedCollisionFrames[j-1][k]); 152 | } 153 | }; 154 | 155 | diffMainArray.push(diffMainElement); 156 | diffCollisionArray.push(diffCollisionElement); 157 | }; 158 | return { 159 | main: diffMainArray, 160 | collision: diffCollisionArray 161 | }; 162 | }; 163 | 164 | 165 | function joinSprites (sprites) { 166 | var keyFrames = {}; 167 | var frames = ['']; 168 | var animations = {}; 169 | 170 | var code = '// src/generatedSprites.js \n// sprites generated with npm run build-sprites\n'; 171 | var lastCode = []; 172 | for (var i = 0; i < sprites.length; i++) { 173 | var sprite = sprites[i]; 174 | var indexAnimation = i; 175 | if(indexAnimation<10) indexAnimation = '0'+i 176 | var spriteName = `anim${indexAnimation}_${sprite.name}` 177 | code += `\nvar ${spriteName} = '${sprite.frames.join('')}';` 178 | lastCode.push(spriteName); 179 | }; 180 | code+=`\nvar animations = [${lastCode}];\n`; 181 | 182 | return code; 183 | } 184 | 185 | 186 | main(function(script){ 187 | fs.writeFile('./src/generatedSprites.js', script, function(err){ 188 | if(err){ 189 | console.log('exception:', err); 190 | return; 191 | } 192 | console.log('file created'); 193 | }); 194 | }); -------------------------------------------------------------------------------- /src/generatedSprites.js: -------------------------------------------------------------------------------- 1 | // src/generatedSprites.js 2 | // sprites generated with npm run build-sprites 3 | 4 | var anim00_fonts = '565758596566696a7576797a8586898a95969798999aa5a6a9aab5b6b9ba01b8b7888755ba98978a01b59a998988877a795501b59a998a897a795501ba88875aaaa99a998a897a796a6901bab9b8b701bab9b8b7aaa99a998a896a69b5875a5501b5877a795a55b8b7585701b8b7a8a79897787768675857bab5aaa9a6a59a9996958a8986857a7976756a6966655a5501a5b9b801bab9b5aaa9a699969586857976756a6966655a55b7a8a797776867585701b8b7aaa99998888779786a695a5901aa9a988a887a786a6968675a5957b9b8b701b9a999897977987868675701b8b75857bab588775a5501b5989755b9b8b7aaa99a01cac9b9b8b7aaa99ab598975501bab5989755cac9b8b79a01b8b79a8887bab5989796958a857a795501a8a79897787768675a55b9b6aaa9a6a59a99898676756a69666501b9b6aaa9a6a59a9996958a8986857a7976756a696665a8a79897888778776867585701a8a7b9b6aaa501bab9b6b5aaa5988878b899897969590199978779776959b7a8a79a958a86857a7501b8b7a8a789867a75bab9b6b5aaa9a6a59996787701bab9b6b5a6a596785857a8a79889867a7675666501a9a79a99958a8986857a76756866bab9b6b5a5978887786a5a59565501bab9b6b5a898978887787767a9a69a9996958a8986857a7976756901a6a596897a796a69655956a8a77877686701aaa99a99867877685a55bab59897967a796a666501a8989796958579767566b7b6aaa6a587775a565501b7b6aaa6a58a77655655a8989796958886856968019695888786856a698a7978775501a8a7989779785a55b9b6aaa9a6a59a999695898685767501b9b6aaa9a6a59a99969589867a777675a8a797785a55018a9896957701b59678776867b9b8b7b6aaa9a6a59a998a89887a79756a66655601b79789887a796a666556b59686787776686701b9b6aaa9a8a7a6a599968678777675b79788876a655958575601b9b6aaa9a8a7a6a5999689867a7978777675696601a6a596956665565501c4b56665565501c4b501847566655655a6a5969501a7978988878685776784756665565501b8b7a69676665857a79789888785776701a999897969a696867666019a8b8a888786857ab8b7585701a79796777667a99a997a796902010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101'; 5 | var anim01_hero01_idle_00 = '2728373846475657596667687677879798a7a9b7b9c7c9d6d9e6e9f5f9010101010101786948685928270101caba86c9b946010101010101c9b946caba860102010101010101010101010101010101'; 6 | var anim02_hero02_punch_01 = '37384748565766676976777886879798a7a9b7bac7cad6d9e6e9f5f901655578694847010178694847655502014d4c4b4a4948474601014d4c4b4a49484746'; 7 | var anim03_hero02_punch_02 = '37384748565766676976777886879798a7a9b7bac7cad6d9e6e9f5f901f4e5d5c6b6a888595849f5e6d6c7b786696657564738370101f5e6d6c7b78669665756473837f4e5d5c6b6a88859584902018d8c7b7a696801018d8c7b7a6968'; 8 | var anim04_hero03_kick_01 = '34354445545556646566677476777886888996979aa6aab6bac6d6e5f501baaa9a978988787776010101baaa9a9789887877760102017e7d7c7b7a797877760101017e7d7c7b7a7978777601'; 9 | var anim05_hero03_kick_02 = '343544455455566465666773757686888996979aa6aab6bac6d6e5f501e67877745746e5baaa9a9789887567010101e5baaa9a9789887567e678777457460102016a695c5b4e4d3e0101016a695c5b4e4d3e01'; 10 | var anim06_hero04_walk_00 = '27283738464756575a666768697677879798a7a9b7bac7cad6dae6eaf5fb010101fae9d97858483929fbeada766656463727010101f6e7d7f5e6d60101f5e6d6f6e7d701010201010101010101010101'; 11 | var anim07_hero05_run_01 = '4a4b58595a5b6768696a78797a7b8889989aa7abb6bac5c9d4e4f30101fdfcecdcccbb96957c57f3e4d4c9c5bab678680101f9e9d9c9baaaa9a8a6998b68fdfcecdcccbbab9a96957c7b67570101f5f4e5e4d6d5c7c6b8b7f9e9d9c9baaaa7a68b0101f2e3d4c5bab9b6aba79a57f5f4e5e4d6d5c7c6b8b7a9a80101feeeddccbb9695f2e3d4c5bab9b69968570101f9e9d9c9bab7aaa9a8a6a59968feeeddccbbaba79a96950101f2e3d4c5b6a79a7b7667f9e9d9c9baaaa6a5680102010101010101010101010101010101'; 12 | var anim08_hero05_run_02 = '464756576667686a7577787986878898a8a9b8bac8cbd8dbe7ecf7fd0101020101'; 13 | var anim09_hero06_speed_punch_00 = '5a5b67686a6b7688898a9798a6a7b5b8b9c3c4cad2d8d9e1e7f0f7010101010102797a7b7c7d7e7f0101010101'; 14 | var anim10_hero07_speed_kick_00 = '6a6b797a7b898a999aa8a9b5b6b8bac7cbdbecfd0101f6ede6d7cac9c8b9b7a7a6a596958577767574686564585655544645fdcbc7bab6b5a99a998a897b7a796b6a0101f3f2e7e5e4e2d9d4d3c7c4c3c2b5b3b2edecdbcac8b9b7a8a7a6a59695857776757468656458565554464501010101010101010201010101fffefdfcfbfaf9f8f7ebda0101010101010101'; 15 | var anim11_hero08_jump_00 = '5859686977788687888a96979899a7b7b8b9bac8cbd8dae7eaf6fa01e8d5c9c6aaa89a89676657564a4847463938372928faf6eae7dacbc8bab8a79997968a8669680201'; 16 | var anim12_hero08_jump_01 = '1819262728293537384547484955575867777879888a989aa8a9b7b8c7d7e702'; 17 | var anim13_hero08_jump_02 = '2728363738464756575866677686878889979aa8aab8bac7cad6e6f60101faf4eae7e5dad8cbc8b9b7a79998968a7877696859f6d6cac7aaa89a897667665756474638373628270101cabbaaa9a8897a7667574948cbbab9b79998968a6901020101010101'; 18 | var anim14_hero09_air_kick_00 = '181926272829353738454748495758677778797a888b989ba8abb7bac6019796958736c6bab7aba89b8b450102017e7d7c7b01'; 19 | var anim15_hero10_dragon_kick_00 = '44455455636465677374757682858693969798a6a7a8a9babbc9ca010101010102ccdddeeeef0101010101'; 20 | var anim16_hero11_get_hit_face_00 = '45465556656667757677788486879697a6a7a8b7b8c7c9d7d9e7eaf6fa0101020101'; 21 | var anim17_hero12_get_hit_body_00 = '595a68696a77787987889798a7b7b8c7c9d8dae7eaf6f90101020101'; 22 | var anim18_hero13_get_hit_legs_00 = '4b4c595a5b5c68696a7778797b87888a8c8d9697a3a6a7a8b4b6b9c5c9d7d8e601010102010101'; 23 | var anim19_hero14_knocked_down_00 = '455565929596979899a2a6a7aab3b8bac7cbd7dbe6f6025152616272737482838485'; 24 | var anim20_hero15_wake_up_00 = 'b7b8b9bac6c7c8c9cacbccd6d7dadbdce3e4e5e6e7eaf2f4f5f6f7f8fb01010101010101010101010102010101010101010101010101'; 25 | var anim21_hero16_defeated_00 = 'e2e3e4e5e6e7f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff02'; 26 | var anim22_hero17 = '37384748565766676976777886879798a7a9b7bac7cad6d9e6e9f5f902'; 27 | var anim23_hero18 = '37384748565766676976777886879798a7a9b7bac7cad6d9e6e9f5f902'; 28 | var anim24_hero19 = '37384748565766676976777886879798a7a9b7bac7cad6d9e6e9f5f902'; 29 | var anim25_hero20 = '37384748565766676976777886879798a7a9b7bac7cad6d9e6e9f5f902'; 30 | var anim26_hero21 = '37384748565766676976777886879798a7a9b7bac7cad6d9e6e9f5f902'; 31 | var anim27_hero22 = '37384748565766676976777886879798a7a9b7bac7cad6d9e6e9f5f902'; 32 | var anim28_z_explosion_01 = '01d6d5cbcac8c7c6c5c4bcbbbab9b8b7b6b5b4acabaaa9a8a7a6a59b9a99989796958f8d8c8b8a89888786857b7a79787776756c6b6a69686766655c5b5a59575655544b4a464501ebeae9e8dad99d9c949384837447443a393635cbcac8bcbbbab7b4acaba6a59b9a98978f8d8c8b8a877b77766a686766655c5b5a59575401f8f3f2e4e3cac9c3c2bab7a6a3a2929187828173726a67664c42343229282423eadad9d6d5c7c4b8b5aaa9a89d9c96958988857875746c6b4b4a47464544360101fae7e2dbd8d785757468544a454419181312f8ebe9e4cac6c5c3c2bab9b7b6a6a3a294938786837a7973726a696766564c423a393534320101faf3e8e3e2dbd8d7c9a7999291858275746855544a452928242319130101f2e7848144181202010101010101010101'; 33 | var anim29_z_explosion_02 = '01b9b5a8a689857a77746701ebe7dad7d3c4b79b99959388866b645c53474337b9b589857a746701fce2b8b6a9a59d91898578764d3227dad7c4b7a8a69b9995938886776b64534701fcebe7e2d3b8b6a9a59d91898578765c4d433732270101010101010201010101010101010101'; 34 | var anim30_z_tilemap_00 = '12131415161718191a1b1c1d2122232425262728292a2b2c2d2e3132333435363738393a3b3c3d3e4142444d4e5152535455565758595a5b5d5e6162636465666768696a6b6d6e7172737475767778797a7b7d7e8182838485868788898a8b8d8e9192939495969798999a9b9c9d9ea1a2a4a5a6a7a8a9aaabadaeb1b2b5b6b7b8b9babbbcbdbec2c3c4c5c6c7c8c9cacbcccdd1d2d3d4d5d6d7d8d9dadbdcdddee2e4e6e8eaeced01ac4abc998979787701bcb399897877b5aca49301eeebe9e7e5e3e1dfd0cfc0bfb0afa09f908f807f706f605f504f4c43403f302f201e11ddd2cdc2bbbab9b8b7b6abaaa9a89c9b9a9998978b8a8988878685837b7a7877767574736867666564635b57565554534a443e3d32312d2201ddd2cecdc2c19c9b9a999897938c8b8a8988878685837c7b7a797877767574735c5b57565554534b4a4948474645443e3d32312d22eeedecebeae9e8e7e6e5e4e3e2e1bfbebdbcb3b2b1b0afaeada7a6a5a2a1a06f6e6d6b6a696261601e1d1c1b1a19181716151413121101fbfaf9f7f6f5ebeae9e7e6e51b1a19171615dcd8d4ccc8c49c98948c88847c78745c58544c48443c38342c282401ccc8c4bdbcb9b8b7b6b5b3adabaaa9a8a7a6a5a4a39c98948c88847c786d6c6b6a6966656463625c544838fbfaf9f7f6f5ebe9e7e6e5dfdedddad9d3d2d1d0cfcecdcbcac3c2c1c09f9e91908f8d81807f7d7a71705f5e5d595756535251504f4e4d49474645434241403f3e3d3b3a3935333231302f2e2d2b2a29232221201b1a1917161501fefdfbfaf9f8f7f6f5f3f2edebe9e8e7e6e5e3deddd3d2cdcbcac3beb2aea28d7d746e68675e5d5958575653524d474645433e3d3b3533322e2d2b2823221e1d1b181716151312dbd7d6d5ccc4bcb9b8b7b6b5abaaa9a8a7a6a5a4927b79787776756c645c544a4802010101010101bab49e7a745301cec2924e4842bab47a7453'; 35 | var animations = [anim00_fonts,anim01_hero01_idle_00,anim02_hero02_punch_01,anim03_hero02_punch_02,anim04_hero03_kick_01,anim05_hero03_kick_02,anim06_hero04_walk_00,anim07_hero05_run_01,anim08_hero05_run_02,anim09_hero06_speed_punch_00,anim10_hero07_speed_kick_00,anim11_hero08_jump_00,anim12_hero08_jump_01,anim13_hero08_jump_02,anim14_hero09_air_kick_00,anim15_hero10_dragon_kick_00,anim16_hero11_get_hit_face_00,anim17_hero12_get_hit_body_00,anim18_hero13_get_hit_legs_00,anim19_hero14_knocked_down_00,anim20_hero15_wake_up_00,anim21_hero16_defeated_00,anim22_hero17,anim23_hero18,anim24_hero19,anim25_hero20,anim26_hero21,anim27_hero22,anim28_z_explosion_01,anim29_z_explosion_02,anim30_z_tilemap_00]; 36 | -------------------------------------------------------------------------------- /src/gameSetup.js: -------------------------------------------------------------------------------- 1 | 2 | var mainScene = Scene({}); 3 | var playerController = PlayerController([player]); 4 | 5 | var aIControllers = []; 6 | 7 | var enemyConfigurations = [ 8 | [0, '#346856', 10], 9 | [1, '#306230', 10], 10 | [2, '#768448', 20], // 69ccef 11 | [3, '#7e8416', 20], // 1ae0b8 12 | [4, '#8fcc3e', 30], // 8fcc3e 13 | [5, '#7bc67b', 30], // fe1111 14 | [6, '#F6FF97', 40], // fe1111 15 | [7, '#9bbc0f', 50] // fe1111 16 | ]; 17 | 18 | mainScene.create = function(){ 19 | 20 | this.loadIntro(); 21 | 22 | this.enemyCounter = 0; 23 | this.add(player); 24 | this.following = player; 25 | this.enemiesToSummon = []; 26 | this.lastCheckPoint = 0; 27 | 28 | var map = [0]; 29 | for (var i = 1; i < 150; i++) { 30 | var tile = 4; 31 | if(i%15==0){ 32 | map[i-1] = 3; 33 | map[i-10] = 0; 34 | }; 35 | map.push(tile); 36 | } 37 | map[5] = 1; 38 | map[20] = 1; 39 | map[35] = 1; 40 | map[50] = 1; 41 | 42 | for (var i = 0; i < map.length; i++) { 43 | this.add(Tile([i*16*2, 118+16*4, map[i]])); 44 | } 45 | 46 | mainScene.maxWidth = map.length*32; 47 | 48 | this.sections = [ 49 | // 0 50 | [32*15,[],[], matrixScript[0]], 51 | [32*15,[[32*10, 0]],[[0,0],[0,0],[1]]], 52 | // 1 53 | [32*30,[],[]], 54 | [32*30,[[32*25, 1], [32*27, 1]],[[1],[1,1],[],[2]]], 55 | 56 | // 2 57 | [32*45,[],[]], 58 | [32*45,[[32*40, 4]],[],matrixScript[1]], 59 | // 3 60 | [32*60,[],[],[['operator: i cant believe it!', 2]]], 61 | [32*60,[[32*58, 2]],[[1,1],[0,0],[1,1],[],[3]]], 62 | // 4 63 | [32*75,[],[]], 64 | [32*75,[[32*69,0],[32*71,0],[32*73, 3]],[[0,1],[0,0],[1,0]]], 65 | // 5 66 | [32*90,[],[]], 67 | [32*90,[[32*85, 5]],[], matrixScript[2]], 68 | // 6 69 | [32*105,[],[], matrixScript[3]], 70 | [32*105,[],[[0,0],[1,1],[0,0,0],[1,1,1],[],[],[0,0,1,1],[1,0,0,1],[],[],[],[2]]], 71 | // 7 72 | [32*120,[],[], [['trinity: hurry, neo!', 2]]], 73 | [32*120,[],[[5, 6]], matrixScript[4]], 74 | // 8 75 | [32*135,[],[]], 76 | [32*135,[[32*130, 7]], [], matrixScript[5]], 77 | // 9 78 | [32*150,[],[]], 79 | [32*150,[],[], matrixScript[6]] 80 | ]; 81 | mainScene.limit = [0, 320]; 82 | //this.loadSection(0); 83 | 84 | this.add(new Heart([32*19,120+12*4, 6])); 85 | this.add(new Heart([32*34,120+12*4, 6])); 86 | this.add(new Disquette([32*49,120+12*4, 6])); 87 | this.add(new Heart([32*64,120+12*4, 6])); 88 | this.add(new Heart([32*79,120+12*4, 6])); 89 | this.add(new Disquette([32*94,120+12*4, 6])); 90 | this.add(new Heart([32*109,120+12*4, 6])); 91 | this.add(new Heart([32*124,120+12*4, 6])); 92 | 93 | this.loadCheckPoint(0*2); 94 | this.loadCheckPoint(0*2); 95 | }; 96 | 97 | mainScene.loadIntro = function(){ 98 | var title = Text([140, 35, 'the matr13k']); 99 | title.color = '#306230'; 100 | title.size = 2; 101 | this.add(title); 102 | var title2 = Text([140, 35, ' 13k']); 103 | title2.color = '#9bbc0f'; 104 | title2.size = 2; 105 | this.add(title2); 106 | 107 | var madeby = Text([170, 55, 'made by agar3s']); 108 | madeby.color = '#9bbc0f'; 109 | madeby.size = 1; 110 | this.add(madeby); 111 | 112 | var controlsA = Text([160, 100, 'arrow keys to move']); 113 | controlsA.color = '#306230'; 114 | controlsA.size = 1; 115 | this.add(controlsA); 116 | var controlsB = Text([160, 112, '(s key) to punch']); 117 | controlsB.color = '#306230'; 118 | controlsB.size = 1; 119 | this.add(controlsB); 120 | var controlsC = Text([160, 124, '(d key) to kick']); 121 | controlsC.color = '#306230'; 122 | controlsC.size = 1; 123 | this.add(controlsC); 124 | var controlsD = Text([160, 136, '(space key) to jump']); 125 | controlsD.color = '#306230'; 126 | controlsD.size = 1; 127 | this.add(controlsD); 128 | 129 | var controlsE = Text([320, 100, '(> > s) special punch']); 130 | controlsE.color = '#306230'; 131 | controlsE.size = 1; 132 | this.add(controlsE); 133 | 134 | var controlsF = Text([320, 112, '(> > d) special kick']); 135 | controlsF.color = '#306230'; 136 | controlsF.size = 1; 137 | this.add(controlsF); 138 | 139 | var controlsG = Text([480, 220, 'your progress is down here']); 140 | controlsG.color = '#306230'; 141 | controlsG.size = 1; 142 | this.add(controlsG); 143 | var controlsH = Text([480, 220, ' here']); 144 | controlsH.color = '#9bbc0f'; 145 | controlsH.size = 1; 146 | this.add(controlsH); 147 | 148 | /* 149 | var colorA = Text([50, 100, '00000']); 150 | colorA.color = '#306230'; 151 | this.add(colorA); 152 | var colorB = Text([50, 110, '00000']); 153 | colorB.color = '#346856'; 154 | this.add(colorB); 155 | var colorC = Text([50, 120, '00000']); 156 | colorC.color = '#768448'; 157 | this.add(colorC); 158 | var colorD = Text([50, 130, '00000']); 159 | colorD.color = '#7e8416'; 160 | this.add(colorD); 161 | var colorE = Text([50, 140, '00000']); 162 | colorE.color = '#8fcc3e'; 163 | this.add(colorE); 164 | var colorF = Text([50, 150, '00000']); 165 | colorF.color = '#7bc67b'; 166 | this.add(colorF); 167 | var colorG = Text([50, 160, '00000']); 168 | colorG.color = '#F6FF97'; 169 | this.add(colorG); 170 | var colorH = Text([50, 170, '00000']); 171 | colorH.color = '#9bbc0f'; 172 | this.add(colorH);*/ 173 | //colorB.color = '#306230'; 174 | 175 | } 176 | 177 | mainScene.loadCheckPoint = function(point) { 178 | var distance = this.sections[point][0]; 179 | this.enemyCounter = 0; 180 | player.dx = distance-32*15; 181 | player.x = player.dx; 182 | this.x = -player.x; 183 | mainScene.limit = [0, distance-32*5]; 184 | this.loadSection(point); 185 | } 186 | 187 | mainScene.gameOver = function(player){ 188 | //this.remove(player); 189 | player.hitPoints = basePlayerStat.maxHp; 190 | playerController.fighter = player; 191 | this.enemiesToSummon = []; 192 | for (var i = aIControllers.length - 1; i >= 0; i--) { 193 | this.remove(aIControllers[i].fighter); 194 | aIControllers.splice(i, 1); 195 | } 196 | // remove aIcontrollers with enemies 197 | this.loadCheckPoint(this.lastCheckPoint); 198 | } 199 | 200 | 201 | mainScene.updateData = function(time, dt) { 202 | playerController.update(time, dt); 203 | for (var i = 0; i < aIControllers.length; i++) { 204 | aIControllers[i].update(time, dt); 205 | } 206 | 207 | if(!this.moving && -this.x >= this.limit[1]-320-8*16 && this.enemyCounter==0 && this.enemiesToSummon.length==0) { 208 | mainScene.loadSection(this.currentSectionIndex+1); 209 | } 210 | 211 | this.nextSummon -= dt; 212 | if(this.enemiesToSummon.length>0 && this.nextSummon<0) { 213 | var enemyprops = this.enemiesToSummon.splice(0, 1)[0]; 214 | var enemy = mainScene.loadEnemy([enemyprops[0], enemyprops[1]]); 215 | enemy.setAnimation(11); 216 | enemy.speed = enemyprops[2]; 217 | enemy.y = 0; 218 | enemy.speedY= -250; 219 | enemy.dy = 0; 220 | enemy.locked = true; 221 | this.nextSummon = 0.5; 222 | } 223 | }; 224 | 225 | mainScene.loadSection = function(index) { 226 | if(index>=this.sections.length) { 227 | return; 228 | } 229 | 230 | this.currentSectionIndex = index; 231 | var section = JSON.parse(JSON.stringify(this.sections[this.currentSectionIndex])); 232 | mainScene.moveToLimit(this.limit[1]-320, section[0]); 233 | for (var i = 0; i < section[1].length; i++) { 234 | this.loadEnemy(section[1][i]); 235 | } 236 | this.enemyPool = section[2].reverse(); 237 | if(i==0) { 238 | this.summonEnemies(-(this.limit[1]-320), 2); 239 | } 240 | if (section[3]) { 241 | setTimeout(function(){ 242 | hudScene.setDialoguePipeline(section[3]); 243 | }, 1500) 244 | } 245 | this.lastCheckPoint = (~~(index/2))*2; 246 | }; 247 | 248 | mainScene.loadEnemy = function(props) { 249 | var enemyConfig = enemyConfigurations[props[1]]; 250 | var enemy = Fighter([props[0], 120, FIGHTER_STATUS_IDS[0], enemyConfig[1]]); 251 | this.add(enemy); 252 | enemy.hitPoints = enemyConfig[2]; 253 | aIControllers.push(AIController([enemy, enemyConfig[0]])); 254 | this.enemyCounter += 1; 255 | return enemy; 256 | }; 257 | 258 | mainScene.removeEnemy = function(enemy) { 259 | this.enemyCounter -= 1; 260 | for (var i = 0; i < aIControllers.length; i++) { 261 | if(aIControllers[i].fighter.id == enemy.id){ 262 | aIControllers.splice(i, 1); 263 | break; 264 | } 265 | } 266 | this.remove(enemy); 267 | mainScene.summonEnemies(this.x, 0); 268 | if (this.enemyCounter==0&&this.enemiesToSummon.length==0) { 269 | hudScene.goMessage.active = true; 270 | } 271 | }; 272 | 273 | mainScene.summonEnemies = function(xOffset, delay) { 274 | if(!this.enemyPool.length) return; 275 | var enemiesToSummon = this.enemyPool.pop(); 276 | for (var i = 0; i < enemiesToSummon.length; i++) { 277 | var enemyType = enemiesToSummon[i]; 278 | var x = -xOffset + (i%2==0?0:32*8); 279 | 280 | this.nextSummon = 0.5 + delay; 281 | 282 | this.enemiesToSummon.push([x, enemyType, i%2==0?250:-250]); 283 | } 284 | }; 285 | 286 | mainScene.displayLevelUpScene = function() { 287 | levelUpScene.active = true; 288 | hudScene.active = false; 289 | player.locked = true 290 | } 291 | 292 | sceneManager.add(mainScene); 293 | 294 | 295 | -------------------------------------------------------------------------------- /src/fighterController.js: -------------------------------------------------------------------------------- 1 | 2 | function CharacterController(props) { 3 | return { 4 | fighter: props[0], 5 | update: function(dt) {} 6 | } 7 | } 8 | 9 | function PlayerController(props) { 10 | var base = CharacterController(props); 11 | base.fighter.human = true; 12 | base.fighter.hitPoints = basePlayerStat.maxHp; 13 | base.fighter.targetHit = 1; 14 | base.fighter.typeHit = 2; 15 | base.fighter.orientation = 1; 16 | base.lastTime = { 17 | left: 0, 18 | right: 0 19 | }; 20 | base.previousStateKey = { 21 | left: false, 22 | right: false 23 | }; 24 | 25 | var controller = { 26 | update: function(time, dt) { 27 | if(levelUpScene.active) return this.controlInterface(time, dt); 28 | if(mainScene.moving){ 29 | this.fighter.speed = 0; 30 | return; 31 | } 32 | var fighter = this.fighter; 33 | if(fighter.locked) return; 34 | fighter.speed = 0; 35 | var hitLock = false; 36 | // punch 37 | if(keyMap&keys[inputs.PUNCH]) { 38 | fighter.punch(); 39 | hitLock = fighter.y == 120; 40 | } 41 | 42 | // kick 43 | if(keyMap&keys[inputs.KICK]) { 44 | fighter.kick(); 45 | hitLock = fighter.y == 120; 46 | } 47 | 48 | // move to the left 49 | if(!hitLock) { 50 | if(keyMap&keys[inputs.LEFT]) { 51 | 52 | if(!this.previousStateKey.left) { 53 | if(fighter.orientation==0 && time-this.lastTime.left<300){ 54 | fighter.run(); 55 | }else if(fighter.orientation==1 && time-this.lastTime.left<1000){ 56 | fighter.turnSide(); 57 | } 58 | } 59 | 60 | if (this.simpleTurnMode&&fighter.orientation==1) { 61 | fighter.turnSide(); 62 | } 63 | 64 | fighter.move(0); 65 | 66 | this.lastTime.left = time; 67 | this.previousStateKey.left = true; 68 | this.previousStateKey.right = true; 69 | } else { 70 | this.previousStateKey.left = false; 71 | } 72 | 73 | // move to the right 74 | if(keyMap&keys[inputs.RIGHT]) { 75 | if(!this.previousStateKey.right) { 76 | if(fighter.orientation==1 && time-this.lastTime.right<300){ 77 | fighter.run(); 78 | } else if(fighter.orientation==0 && time-this.lastTime.right<1000){ 79 | fighter.turnSide(); 80 | } 81 | } 82 | if(this.simpleTurnMode && fighter.orientation==0){ 83 | fighter.turnSide(); 84 | } 85 | 86 | fighter.move(1); 87 | 88 | this.lastTime.right = time; 89 | this.previousStateKey.right = true; 90 | this.previousStateKey.left = true; 91 | } else { 92 | this.previousStateKey.right = false; 93 | } 94 | } 95 | 96 | // I don't know 97 | if(keyMap&keys[inputs.ENTER]) { 98 | fighter.orientation ^= 1; 99 | } 100 | 101 | // jump 102 | if(keyMap&keys[inputs.JUMP]) { 103 | fighter.jump(); 104 | } 105 | }, 106 | controlInterface: function(time, dt) { 107 | if(keyMap&keys[inputs.RIGHT]) { 108 | if(!this.previousStateKey.right){ 109 | this.previousStateKey.right = true; 110 | levelUpScene.setOption(levelUpScene.indexOption+1); 111 | } 112 | } else { 113 | this.previousStateKey.right = false; 114 | } 115 | 116 | if(keyMap&keys[inputs.LEFT]) { 117 | if(!this.previousStateKey.left){ 118 | this.previousStateKey.left = true; 119 | levelUpScene.setOption(levelUpScene.indexOption-1); 120 | } 121 | } else { 122 | this.previousStateKey.left = false; 123 | } 124 | 125 | if((keyMap&keys[inputs.PUNCH]) || (keyMap&keys[inputs.KICK])) { 126 | levelUpScene.applyStat(); 127 | levelUpScene.active = false; 128 | hudScene.active = true; 129 | player.locked = false; 130 | } 131 | } 132 | } 133 | extendFunction(base, controller) 134 | return controller 135 | } 136 | 137 | function AIController(props) { 138 | var base = CharacterController(props); 139 | var actions = [ 140 | base.fighter.move, 141 | base.fighter.run, 142 | base.fighter.jump, 143 | base.fighter.turnSide, 144 | base.fighter.punch, 145 | base.fighter.kick 146 | ]; 147 | 148 | 149 | function getDistanceToPlayer(fighter){ 150 | return Math.abs(fighter.x - player.x); 151 | } 152 | function getOrientationToPlayer(fighter) { 153 | return fighter.x - player.x < 0 ? 1: 0; 154 | } 155 | function closeDistance(fighter) { 156 | var distance = getDistanceToPlayer(fighter); 157 | if(distance>24 && distance<300) { 158 | var orientation = getOrientationToPlayer(fighter); 159 | if(fighter.orientation!=orientation){ 160 | fighter.turnSide() 161 | } 162 | fighter.move(orientation); 163 | } 164 | return distance>=24; 165 | } 166 | function punch(fighter) { 167 | fighter.punch(); 168 | return true; 169 | } 170 | 171 | function kick(fighter) { 172 | fighter.kick(); 173 | return true; 174 | } 175 | 176 | function runToSpecial(fighter) { 177 | var distance = getDistanceToPlayer(fighter); 178 | if(distance>270) return false; 179 | if(!fighter.running)fighter.run(); 180 | fighter.running = true; 181 | fighter.move(); 182 | return distance>60; 183 | } 184 | 185 | function runToSpecialAlert(fighter) { 186 | var distance = getDistanceToPlayer(fighter); 187 | if(distance>270) return false; 188 | if(!fighter.running)fighter.run(); 189 | fighter.running = true; 190 | fighter.move(); 191 | if(distance < 70 && player.velocity>100) { 192 | fighter.jump(); 193 | return false; 194 | } 195 | return distance>60; 196 | } 197 | 198 | function runToClose(fighter) { 199 | var distance = getDistanceToPlayer(fighter); 200 | if(distance>270) return false; 201 | if(!fighter.running)fighter.run(); 202 | fighter.running = true; 203 | fighter.move(); 204 | return distance>24; 205 | } 206 | 207 | function runToCloseAlert(fighter) { 208 | var distance = getDistanceToPlayer(fighter); 209 | if(distance>270) return false; 210 | if(!fighter.running)fighter.run(); 211 | fighter.running = true; 212 | fighter.move(); 213 | 214 | if(distance < 70 && player.velocity>100) { 215 | fighter.jump(); 216 | return false; 217 | } 218 | 219 | return distance>24; 220 | } 221 | 222 | function resetRun(fighter) { 223 | fighter.running = false; 224 | return false; 225 | } 226 | 227 | function takeDistance(fighter){ 228 | var distance = getDistanceToPlayer(fighter); 229 | if(distance>10 && distance<120) { 230 | var orientation = getOrientationToPlayer(fighter); 231 | fighter.move(orientation^1); 232 | } 233 | return true; 234 | } 235 | function wait(){return true;} 236 | 237 | function alert(fighter) { 238 | var distance = getDistanceToPlayer(fighter); 239 | var orientation = getOrientationToPlayer(fighter); 240 | if(fighter.orientation!=orientation){ 241 | fighter.turnSide(); 242 | } 243 | if(distance < 60 && player.velocity>100) { 244 | fighter.jump(); 245 | return false; 246 | }else if(distance<40){ 247 | fighter.kick(); 248 | } 249 | return true; 250 | } 251 | 252 | var basicPuncher = [[closeDistance, 1.5], [wait, 0.1], [punch, 0.5], [wait, 0.1], [takeDistance, 1]]; 253 | var basicKicker = [[closeDistance, 1.4], [wait, 0.1], [kick, 1], [wait, 0.2], [takeDistance, 0.5]]; 254 | var fasterPuncher = [[closeDistance, 0.2], [punch, 0.1], [kick, 0.1], [wait, 0.3], [closeDistance, 0.1], [runToSpecial, 1], [punch, 0.3], [wait, 1], [closeDistance, 0.1], [punch, 0.5], [takeDistance, 0.8], [resetRun, 0.1], [wait, 0.5]]; 255 | var fasterKicker = [[closeDistance, 0.2], [kick, 0.3], [wait, 0.4], [closeDistance, 0.2], [runToSpecial, 0.6], [closeDistance, 0.1],[kick, 0.3], [wait, 0.6], [closeDistance, 0.1],[kick, 0.5], [takeDistance, 1], [resetRun, 0.1], [wait, 0.6]]; 256 | var jumper = [[alert, 1.5], [punch, 0.3], [closeDistance, 0.2],[wait, 0.2], [punch, 0.3],[takeDistance, 0.4], [wait, 0.3], [closeDistance, 0.5]]; 257 | var aggressive = [[alert, 1.7], [closeDistance, 0.2], [alert, 0.5], [runToClose, 1], [wait, 0.1], [closeDistance, 0.1], [punch, 1], [closeDistance, 0.1],[kick,1], [closeDistance, 0.1], [takeDistance, 0.5], [resetRun, 0.1], [closeDistance, 0.1], [punch, 1]]; 258 | 259 | var aggressiveA = [[closeDistance, 0.1], [alert, 0.6], [runToCloseAlert, 0.6], [closeDistance, 0.1], [alert, 0.6], [resetRun, 0.1], [runToSpecialAlert, 0.6], [punch, 0.6], [takeDistance, 0.5],[closeDistance, 0.1], [kick, 0.8], [resetRun, 0.1]]; 260 | 261 | var aggressiveS = [[closeDistance, 0.1], [runToSpecialAlert, 0.6], [closeDistance, 0.1], [kick, 1], [resetRun, 0.1], [closeDistance, 0.1], [runToSpecialAlert, 1], [closeDistance, 0.1], [punch, 1], [resetRun, 0.1]]; 262 | 263 | var heuristics = [basicPuncher, basicKicker, fasterPuncher, fasterKicker, jumper, aggressive, aggressiveA, aggressiveS]; 264 | 265 | var controller = { 266 | id: (Math.random()).toString(16), 267 | time: 0, 268 | indexAction: 100, 269 | nextActionTime: 0, 270 | currentAction: [], 271 | actionPipeline: heuristics[props[1] || 0], 272 | programNextAction: function(){ 273 | this.indexAction++; 274 | if(this.indexAction >= this.actionPipeline.length) { 275 | this.indexAction = 0; 276 | } 277 | this.currentAction = this.actionPipeline[this.indexAction]; 278 | this.nextActionTime = this.currentAction[1]; 279 | this.time = 0; 280 | }, 281 | update: function(time, dt) { 282 | if(mainScene.moving){ 283 | this.fighter.speed = 0; 284 | return; 285 | } 286 | if(this.fighter.locked) return; 287 | this.fighter.speed = 0; 288 | this.time += dt; 289 | if(this.time > this.nextActionTime) { 290 | this.programNextAction(); 291 | } 292 | var result = this.currentAction[0](this.fighter, dt); 293 | if(!result) this.programNextAction(); 294 | } 295 | } 296 | extendFunction(base, controller) 297 | return controller 298 | } 299 | -------------------------------------------------------------------------------- /src/fighter.js: -------------------------------------------------------------------------------- 1 | // 0: left, 1: right 2 | const CHARACTER_SIDES = [-1, 1]; 3 | const PUNCHS = [1, 2]; 4 | const KICKS = [3, 4]; 5 | 6 | const FIGHTER_STATUS_IDS = [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]; 7 | 8 | const FIGHTER_STATUS = [ 9 | {anim: FIGHTER_STATUS_IDS[0], loop: 1}, // idle 10 | {anim: FIGHTER_STATUS_IDS[1], loop: 0, end: 0}, // punch 01 - ground 11 | {anim: FIGHTER_STATUS_IDS[2], loop: 0, end: 0}, // punch 02 - ground 12 | {anim: FIGHTER_STATUS_IDS[3], loop: 0, end: 0}, // kick 01 - ground 13 | {anim: FIGHTER_STATUS_IDS[4], loop: 0, end: 0}, // kick 02 - ground 14 | {anim: FIGHTER_STATUS_IDS[5], loop: 1}, // walk - ground 15 | {anim: FIGHTER_STATUS_IDS[6], loop: 1}, // run 01 - anim18 16 | {anim: FIGHTER_STATUS_IDS[7], loop: 0, end: 0}, // run 02 - anim19 17 | {anim: FIGHTER_STATUS_IDS[8], loop: 0, end: 0}, // punch running 18 | {anim: FIGHTER_STATUS_IDS[9], loop: 0, end: 0}, // kick running 19 | {anim: FIGHTER_STATUS_IDS[10], loop: 0, end: 11}, // jump start - anim 22 20 | {anim: FIGHTER_STATUS_IDS[11], loop: 1}, // jump idle - anim 23 21 | {anim: FIGHTER_STATUS_IDS[12], loop: 0, end: 0}, // jump land - anim 24 22 | {anim: FIGHTER_STATUS_IDS[13], loop: 0, end: 11}, // jump kick 23 | {anim: FIGHTER_STATUS_IDS[14], loop: 1}, // jump-running kick 24 | {anim: FIGHTER_STATUS_IDS[15], loop: 0, end: 0}, // get hit face 25 | {anim: FIGHTER_STATUS_IDS[16], loop: 0, end: 0}, // get hit body 26 | {anim: FIGHTER_STATUS_IDS[17], loop: 0, end: 20}, // get hit legs 27 | {anim: FIGHTER_STATUS_IDS[18], loop: 1}, // knocked down 28 | {anim: FIGHTER_STATUS_IDS[19], loop: 0, end: 0}, // wake up 29 | {anim: FIGHTER_STATUS_IDS[20], loop: 0, end: 19}, // defeated 30 | {anim: FIGHTER_STATUS_IDS[21], loop: 1}, // reserved 1 - anim33 31 | {anim: FIGHTER_STATUS_IDS[22], loop: 1}, // reserved 2 - anim34 32 | {anim: FIGHTER_STATUS_IDS[23], loop: 1}, // reserved 3 - anim35 33 | {anim: FIGHTER_STATUS_IDS[24], loop: 1}, // reserved 4 - anim36 34 | {anim: FIGHTER_STATUS_IDS[25], loop: 1}, // reserved 5 - anim37 35 | {anim: FIGHTER_STATUS_IDS[26], loop: 1} // reserved 6 - anim38 36 | ]; 37 | 38 | const VELOCITIES = [60, 160]; 39 | const DAMAGE_VALUES = [ 40 | 1, // 0 basic punch 41 | 1.5, // 1 basic kick 42 | 4.1, // 2 running punch 43 | 1, // 3 running kick 44 | 2, // 4 jump kick 45 | 5 // 5 dragon kick 46 | ]; 47 | 48 | function Fighter(props) { 49 | var base = Character(props); 50 | var extended = { 51 | speed: 0, 52 | nextPunch: 0, 53 | nextKick: 0, 54 | status: FIGHTER_STATUS[0], 55 | statusIndex: 0, 56 | locked: false, 57 | freezeTime: 0, 58 | brakeSpeed: 0, 59 | baseSpeed: 0, 60 | previousSpeed: 0, 61 | speedY: 0, 62 | damageToApply: 0, 63 | onDamageTime: 0, 64 | continousComboDamage: 0, 65 | nextFlash: 0, 66 | orientation: 1, 67 | removeMeNextTime: false, 68 | drawFrame: function() { 69 | if(this.hitPoints<0){ 70 | var countdown = ~~(this.freezeTime*100); 71 | if(countdown=120) { 130 | this.y = 120; 131 | this.speedY = 0; 132 | if(this.statusIndex!=18){ 133 | if(this.velocity> VELOCITIES[0]){ 134 | this.setAnimation(6); 135 | } else { 136 | this.setAnimation(12); 137 | } 138 | }else { 139 | this.brakeSpeed = 0; 140 | this.baseSpeed = 0; 141 | this.speed = 0; 142 | this.typeHit = this.typeHit ^ 3; 143 | this.targetHit = this.targetHit ^ 3; 144 | this.setAnimation(20, true, 1); 145 | } 146 | } 147 | } 148 | 149 | if (this.speed) { 150 | this.dx += this.speed*dt; 151 | var minLimit = mainScene.limit[0] - 10; 152 | var maxLimit = mainScene.limit[1] - 40; 153 | if(this.dx < minLimit){ 154 | this.dx = minLimit; 155 | }else if(this.dx > maxLimit){ 156 | this.dx = maxLimit; 157 | } 158 | this.x = ~~(this.dx/this.pixelSize)*this.pixelSize; 159 | } else { 160 | if (this.statusIndex==5) { 161 | this.setAnimation(0); 162 | } else if(this.statusIndex ===6) { 163 | this.setAnimation(7); 164 | } 165 | this.velocity = 0; 166 | } 167 | }, 168 | jump: function() { 169 | if(this.locked) return; 170 | if(this.y != 120) return 171 | this.setAnimation(10); 172 | this.speedY -= 650; 173 | this.y -= this.pixelSize; 174 | play(jumpSound); 175 | }, 176 | hit: function(animationIndex, damageValueIndex){ 177 | if(this.locked) return true; 178 | var soundIndex = ~~(Math.random()*3); 179 | // running? super kick 180 | if(this.velocity === VELOCITIES[1]) { 181 | this.baseSpeed = CHARACTER_SIDES[this.orientation]*VELOCITIES[1]*0.8; 182 | this.brakeSpeed = -this.baseSpeed*0.1; 183 | if(this.y!=120) { 184 | this.setAnimation(14, true); 185 | this.damageToApply = DAMAGE_VALUES[5]; 186 | } else { 187 | this.setAnimation(animationIndex, true); 188 | this.damageToApply = DAMAGE_VALUES[damageValueIndex]; 189 | } 190 | play(punchSounds[soundIndex]); 191 | return true; 192 | } 193 | // jump kick 194 | if (this.y!=120) { 195 | this.setAnimation(13, true); 196 | play(punchSounds[soundIndex]); 197 | this.damageToApply = DAMAGE_VALUES[4]; 198 | return true; 199 | } 200 | 201 | return false; 202 | }, 203 | kick: function() { 204 | if(this.hit(9, 2)) return; 205 | 206 | // idle kick 207 | if(this.statusIndex === 3 || this.statusIndex === 4) return; 208 | if(this.statusIndex !== 0 && this.statusIndex !== 5) return; 209 | 210 | this.setAnimation(KICKS[this.nextKick]); 211 | this.nextKick++; 212 | this.speed = 0; 213 | this.damageToApply = DAMAGE_VALUES[1]; 214 | if(this.nextKick === KICKS.length) this.nextKick = 0 215 | play(punchSounds[~~(Math.random()*3)]); 216 | }, 217 | punch: function() { 218 | if(this.hit(8, 2)) return; 219 | 220 | // idle punch 221 | if(this.statusIndex === 1 || this.statusIndex === 2) return; 222 | if(this.statusIndex !== 0 && this.statusIndex !== 5) return; 223 | 224 | this.setAnimation(PUNCHS[this.nextPunch]); 225 | this.nextPunch++; 226 | this.speed = 0; 227 | this.damageToApply = DAMAGE_VALUES[0]; 228 | play(punchSounds[~~(Math.random()*3)]); 229 | if(this.nextPunch === PUNCHS.length) this.nextPunch = 0 230 | }, 231 | move: function(side) { 232 | if(this.locked) return; 233 | if((this.statusIndex !==5&&this.statusIndex !=6&&this.statusIndex!=7)&&this.y==120) { 234 | this.setAnimation(5); 235 | } 236 | this.velocity = this.velocity!=0?this.velocity:VELOCITIES[0]; 237 | if(side==undefined){ 238 | side = this.orientation; 239 | }else if(side!=this.orientation) { 240 | this.velocity = VELOCITIES[0]; 241 | if(this.statusIndex !==5)this.setAnimation(5); 242 | } 243 | this.speed = CHARACTER_SIDES[side]*this.velocity; 244 | }, 245 | run: function() { 246 | this.setAnimation(6); 247 | this.velocity = VELOCITIES[1]; 248 | }, 249 | turnSide: function() { 250 | this.orientation ^= 1; 251 | }, 252 | setAnimation: function(statusIndex, lock, freezeTime) { 253 | this.statusIndex = statusIndex 254 | this.status = FIGHTER_STATUS[statusIndex]; 255 | this.animation = animations[this.status.anim]; 256 | this.collisionAnimation = collisionAnimations[this.status.anim]; 257 | this.animIndex = 0; 258 | if (lock) { 259 | this.freezeTime = freezeTime || this.animation.length/20; 260 | this.locked = true; 261 | } 262 | }, 263 | animationEnds: function() { 264 | if(this.status.loop || this.locked) return; 265 | this.colliding = false; 266 | this.setAnimation(this.status.end) 267 | }, 268 | setDamage: function(damage, y, kickerOrientation) { 269 | if(this.colliding) return false; 270 | if(this.locked) return false; 271 | if(this.statusIndex===18) return false; 272 | this.colliding = true; 273 | if(this.human){ 274 | damage -= basePlayerStat.defense; 275 | if(damage<=0) return; 276 | } 277 | 278 | var impactOnY = (y - this.y)/this.pixelSize; 279 | var nextStatus = 0; 280 | var factor = 1; 281 | var throwHit = false; 282 | var throwHeight = 0; 283 | var throwDistance = 1; 284 | 285 | if(impactOnY <= 6){ 286 | // impact on face 287 | nextStatus = 15; 288 | factor = 2; 289 | }else if(impactOnY <= 11) { 290 | nextStatus = 16; 291 | // impact on body 292 | factor = 1; 293 | }else { 294 | nextStatus = 17; 295 | // impact on legs 296 | factor = 0.6; 297 | throwHit = true; 298 | throwHeight = 100; 299 | throwDistance = 0.5; 300 | } 301 | 302 | play(hitSound[~~(Math.random()*3)]); 303 | // check damage on combo 304 | if(+new Date() - this.onDamageTime < 350) { 305 | // connect combo 306 | this.continousComboDamage++; 307 | factor += this.continousComboDamage*0.1; 308 | if(this.continousComboDamage>3 && factor*damage>2){ 309 | throwHit = true; 310 | throwHeight = 200; 311 | } 312 | }else { 313 | this.continousComboDamage = 0; 314 | } 315 | if(factor*damage>4) { 316 | throwHeight = 100; 317 | throwHit = true; 318 | throwDistance = 2; 319 | } 320 | this.onDamageTime = + new Date(); 321 | 322 | // calculate damage 323 | this.hitPoints -= factor*damage; 324 | 325 | if(this.hitPoints<0) { 326 | throwHit = true; 327 | throwHeight = 300; 328 | } 329 | if(this.y!=120){ 330 | throwHeight = -200; 331 | } 332 | 333 | if (throwHit) { 334 | nextStatus = 18; 335 | this.baseSpeed = -CHARACTER_SIDES[kickerOrientation]*VELOCITIES[1]*throwDistance; 336 | this.brakeSpeed = -this.baseSpeed*2; 337 | this.speedY -= 200 + throwHeight; 338 | this.y -= this.pixelSize; 339 | this.setAnimation(nextStatus, true, 1); 340 | this.typeHit = this.typeHit ^ 3; 341 | this.targetHit = this.targetHit ^ 3; 342 | } else { 343 | this.speed = 0; 344 | this.setAnimation(nextStatus, true); 345 | } 346 | 347 | if(!this.human) { 348 | enemyId.setText(this.id); 349 | enemyId.color = this.color; 350 | enemyPunched = this; 351 | } 352 | return true; 353 | }, 354 | damage: function(target, y) { 355 | var orientation = this.x > target.x ? 1: 0; 356 | var damage = this.damageToApply; 357 | if(this.human){ 358 | damage += basePlayerStat.damage; 359 | } 360 | return target.setDamage(damage || 2, y, orientation); 361 | }, 362 | pick: function(pickable) { 363 | pickable.affectFighter(this); 364 | mainScene.remove(pickable); 365 | }, 366 | incrementHp: function(hp) { 367 | this.hitPoints += hp; 368 | if(this.human && this.hitPoints>basePlayerStat.maxHp){ 369 | this.hitPoints = basePlayerStat.maxHp; 370 | } 371 | }, 372 | resetHp: function(){ 373 | if(this.human){ 374 | this.hitPoints = basePlayerStat.maxHp; 375 | } 376 | } 377 | }; 378 | extendFunction(base, extended) 379 | return extended 380 | } -------------------------------------------------------------------------------- /assets/fonts.sprite: -------------------------------------------------------------------------------- 1 | ________________ 2 | ________________ 3 | ________________ 4 | ________________ 5 | ________________ 6 | ______MMMM______ 7 | _____MM__MM_____ 8 | _____MM__MM_____ 9 | _____MM__MM_____ 10 | _____MMMMMM_____ 11 | _____MM__MM_____ 12 | _____MM__MM_____ 13 | ________________ 14 | ________________ 15 | ________________ 16 | ________________ 17 | //new Frame 18 | ________________ 19 | ________________ 20 | ________________ 21 | ________________ 22 | ________________ 23 | _____MMMMM______ 24 | _____MM__MM_____ 25 | _____MM__MM_____ 26 | _____MMMMM______ 27 | _____MM__MM_____ 28 | _____MM__MM_____ 29 | _____MMMMM______ 30 | ________________ 31 | ________________ 32 | ________________ 33 | ________________ 34 | //new Frame 35 | ________________ 36 | ________________ 37 | ________________ 38 | ________________ 39 | ________________ 40 | ______MMMM______ 41 | _____MM__MM_____ 42 | _____MM_________ 43 | _____MM_________ 44 | _____MM_________ 45 | _____MM__MM_____ 46 | ______MMMM______ 47 | ________________ 48 | ________________ 49 | ________________ 50 | ________________ 51 | //new Frame 52 | ________________ 53 | ________________ 54 | ________________ 55 | ________________ 56 | ________________ 57 | _____MMMMM______ 58 | _____MM__MM_____ 59 | _____MM__MM_____ 60 | _____MM__MM_____ 61 | _____MM__MM_____ 62 | _____MM__MM_____ 63 | _____MMMMM______ 64 | ________________ 65 | ________________ 66 | ________________ 67 | ________________ 68 | //new Frame 69 | ________________ 70 | ________________ 71 | ________________ 72 | ________________ 73 | ________________ 74 | _____MMMMMM_____ 75 | _____MM_________ 76 | _____MM_________ 77 | _____MMMM_______ 78 | _____MM_________ 79 | _____MM_________ 80 | _____MMMMMM_____ 81 | ________________ 82 | ________________ 83 | ________________ 84 | ________________ 85 | //new Frame 86 | ________________ 87 | ________________ 88 | ________________ 89 | ________________ 90 | ________________ 91 | _____MMMMMM_____ 92 | _____MM_________ 93 | _____MM_________ 94 | _____MMMM_______ 95 | _____MM_________ 96 | _____MM_________ 97 | _____MM_________ 98 | ________________ 99 | ________________ 100 | ________________ 101 | ________________ 102 | //new Frame 103 | ________________ 104 | ________________ 105 | ________________ 106 | ________________ 107 | ________________ 108 | ______MMMM______ 109 | _____MM__MM_____ 110 | _____MM_________ 111 | _____MM_MMM_____ 112 | _____MM__MM_____ 113 | _____MM__MM_____ 114 | ______MMMMM_____ 115 | ________________ 116 | ________________ 117 | ________________ 118 | ________________ 119 | //new Frame 120 | ________________ 121 | ________________ 122 | ________________ 123 | ________________ 124 | ________________ 125 | _____MM__MM_____ 126 | _____MM__MM_____ 127 | _____MM__MM_____ 128 | _____MMMMMM_____ 129 | _____MM__MM_____ 130 | _____MM__MM_____ 131 | _____MM__MM_____ 132 | ________________ 133 | ________________ 134 | ________________ 135 | ________________ 136 | //new Frame 137 | ________________ 138 | ________________ 139 | ________________ 140 | ________________ 141 | ________________ 142 | ______MMMM______ 143 | _______MM_______ 144 | _______MM_______ 145 | _______MM_______ 146 | _______MM_______ 147 | _______MM_______ 148 | ______MMMM______ 149 | ________________ 150 | ________________ 151 | ________________ 152 | ________________ 153 | //new Frame 154 | ________________ 155 | ________________ 156 | ________________ 157 | ________________ 158 | ________________ 159 | ______MMMM______ 160 | _______MM_______ 161 | _______MM_______ 162 | _______MM_______ 163 | _______MM_______ 164 | _____M_MM_______ 165 | ______MM________ 166 | ________________ 167 | ________________ 168 | ________________ 169 | ________________ 170 | //new Frame 171 | ________________ 172 | ________________ 173 | ________________ 174 | ________________ 175 | ________________ 176 | _____MM__MM_____ 177 | _____MM__MM_____ 178 | _____MM_MM______ 179 | _____MMMM_______ 180 | _____MM_MM______ 181 | _____MM__MM_____ 182 | _____MM__MM_____ 183 | ________________ 184 | ________________ 185 | ________________ 186 | ________________ 187 | //new Frame 188 | ________________ 189 | ________________ 190 | ________________ 191 | ________________ 192 | ________________ 193 | _____MM_________ 194 | _____MM_________ 195 | _____MM_________ 196 | _____MM_________ 197 | _____MM_________ 198 | _____MM_________ 199 | _____MMMMMM_____ 200 | ________________ 201 | ________________ 202 | ________________ 203 | ________________ 204 | //new Frame 205 | ________________ 206 | ________________ 207 | ________________ 208 | ________________ 209 | ________________ 210 | _____MMM_MM_____ 211 | _____MMMMMM_____ 212 | _____MM_M_M_____ 213 | _____MM_M_M_____ 214 | _____MM_M_M_____ 215 | _____MM___M_____ 216 | _____MM___M_____ 217 | ________________ 218 | ________________ 219 | ________________ 220 | ________________ 221 | //new Frame 222 | ________________ 223 | ________________ 224 | ________________ 225 | ________________ 226 | ________________ 227 | _____MM__MM_____ 228 | _____MM__MM_____ 229 | _____MMM_MM_____ 230 | _____MM_MMM_____ 231 | _____MM__MM_____ 232 | _____MM__MM_____ 233 | _____MM__MM_____ 234 | ________________ 235 | ________________ 236 | ________________ 237 | ________________ 238 | //new Frame 239 | ________________ 240 | ________________ 241 | ________________ 242 | ________________ 243 | ________________ 244 | ______MMMM______ 245 | _____MM__MM_____ 246 | _____MM__MM_____ 247 | _____MM__MM_____ 248 | _____MM__MM_____ 249 | _____MM__MM_____ 250 | ______MMMM______ 251 | ________________ 252 | ________________ 253 | ________________ 254 | ________________ 255 | //new Frame 256 | ________________ 257 | ________________ 258 | ________________ 259 | ________________ 260 | ________________ 261 | _____MMMMM______ 262 | _____MM__MM_____ 263 | _____MM__MM_____ 264 | _____MM__MM_____ 265 | _____MMMMM______ 266 | _____MM_________ 267 | _____MM_________ 268 | ________________ 269 | ________________ 270 | ________________ 271 | ________________ 272 | //new Frame 273 | ________________ 274 | ________________ 275 | ________________ 276 | ________________ 277 | ________________ 278 | ______MMMM______ 279 | _____MM__MM_____ 280 | _____MM__MM_____ 281 | _____MM__MM_____ 282 | _____MM__MM_____ 283 | _____MM__MM_____ 284 | ______MMMM______ 285 | _________MM_____ 286 | ________________ 287 | ________________ 288 | ________________ 289 | //new Frame 290 | ________________ 291 | ________________ 292 | ________________ 293 | ________________ 294 | ________________ 295 | _____MMMMM______ 296 | _____MM__MM_____ 297 | _____MM__MM_____ 298 | _____MM__MM_____ 299 | _____MMMMM______ 300 | _____MM__MM_____ 301 | _____MM__MM_____ 302 | ________________ 303 | ________________ 304 | ________________ 305 | ________________ 306 | //new Frame 307 | ________________ 308 | ________________ 309 | ________________ 310 | ________________ 311 | ________________ 312 | ______MMMM______ 313 | _____MM__MM_____ 314 | _____MM_________ 315 | ______MMMM______ 316 | _________MM_____ 317 | _____MM__MM_____ 318 | ______MMMM______ 319 | ________________ 320 | ________________ 321 | ________________ 322 | ________________ 323 | //new Frame 324 | ________________ 325 | ________________ 326 | ________________ 327 | ________________ 328 | ________________ 329 | _____MMMMMM_____ 330 | _______MM_______ 331 | _______MM_______ 332 | _______MM_______ 333 | _______MM_______ 334 | _______MM_______ 335 | _______MM_______ 336 | ________________ 337 | ________________ 338 | ________________ 339 | ________________ 340 | //new Frame 341 | ________________ 342 | ________________ 343 | ________________ 344 | ________________ 345 | ________________ 346 | _____MM__MM_____ 347 | _____MM__MM_____ 348 | _____MM__MM_____ 349 | _____MM__MM_____ 350 | _____MM__MM_____ 351 | _____MM__MM_____ 352 | ______MMMM______ 353 | ________________ 354 | ________________ 355 | ________________ 356 | ________________ 357 | //new Frame 358 | ________________ 359 | ________________ 360 | ________________ 361 | ________________ 362 | ________________ 363 | _____MM__MM_____ 364 | _____MM__MM_____ 365 | _____MM__MM_____ 366 | _____MM__MM_____ 367 | _____MM__MM_____ 368 | ______MMMM______ 369 | _______MM_______ 370 | ________________ 371 | ________________ 372 | ________________ 373 | ________________ 374 | //new Frame 375 | ________________ 376 | ________________ 377 | ________________ 378 | ________________ 379 | ________________ 380 | _____MM___M_____ 381 | _____MM___M_____ 382 | _____MM_M_M_____ 383 | _____MM_M_M_____ 384 | _____MM_M_M_____ 385 | _____MMMMMM_____ 386 | _____MMM_MM_____ 387 | ________________ 388 | ________________ 389 | ________________ 390 | ________________ 391 | //new Frame 392 | ________________ 393 | ________________ 394 | ________________ 395 | ________________ 396 | ________________ 397 | _____MM__MM_____ 398 | _____MM__MM_____ 399 | ______MMMM______ 400 | _______MM_______ 401 | ______MMMM______ 402 | _____MM__MM_____ 403 | _____MM__MM_____ 404 | ________________ 405 | ________________ 406 | ________________ 407 | ________________ 408 | //new Frame 409 | ________________ 410 | ________________ 411 | ________________ 412 | ________________ 413 | ________________ 414 | _____MM__MM_____ 415 | _____MM__MM_____ 416 | _____MM__MM_____ 417 | ______MMMM______ 418 | _______MM_______ 419 | _______MM_______ 420 | _______MM_______ 421 | ________________ 422 | ________________ 423 | ________________ 424 | ________________ 425 | //new Frame 426 | ________________ 427 | ________________ 428 | ________________ 429 | ________________ 430 | ________________ 431 | _____MMMMMM_____ 432 | _________MM_____ 433 | ________MM______ 434 | _______MM_______ 435 | ______MM________ 436 | _____MM_________ 437 | _____MMMMMM_____ 438 | ________________ 439 | ________________ 440 | ________________ 441 | ________________ 442 | //new Frame 443 | ________________ 444 | ________________ 445 | ________________ 446 | ________________ 447 | ________________ 448 | _______MM_______ 449 | ______M_MM______ 450 | _____MM__MM_____ 451 | _____MM__MM_____ 452 | _____MM__MM_____ 453 | ______MM_M______ 454 | _______MM_______ 455 | ________________ 456 | ________________ 457 | ________________ 458 | ________________ 459 | //new Frame 460 | ________________ 461 | ________________ 462 | ________________ 463 | ________________ 464 | ________________ 465 | _______MM_______ 466 | ______MMM_______ 467 | _______MM_______ 468 | _______MM_______ 469 | _______MM_______ 470 | _______MM_______ 471 | _____MMMMMM_____ 472 | ________________ 473 | ________________ 474 | ________________ 475 | ________________ 476 | //new Frame 477 | ________________ 478 | ________________ 479 | ________________ 480 | ________________ 481 | ________________ 482 | ______MMMM______ 483 | _____MM__MM_____ 484 | _________MM_____ 485 | _______MMM______ 486 | ______MMM_______ 487 | _____MM_________ 488 | _____MMMMMM_____ 489 | ________________ 490 | ________________ 491 | ________________ 492 | ________________ 493 | //new Frame 494 | ________________ 495 | ________________ 496 | ________________ 497 | ________________ 498 | ________________ 499 | _____MMMMMM_____ 500 | ________MM______ 501 | _______MM_______ 502 | ______MMMM______ 503 | _________MM_____ 504 | _____MM__MM_____ 505 | ______MMMM______ 506 | ________________ 507 | ________________ 508 | ________________ 509 | ________________ 510 | //new Frame 511 | ________________ 512 | ________________ 513 | ________________ 514 | ________________ 515 | ________________ 516 | _______MMM______ 517 | ______M_MM______ 518 | _____MM_MM______ 519 | _____MM_MM______ 520 | _____MMMMMM_____ 521 | ________MM______ 522 | ________MM______ 523 | ________________ 524 | ________________ 525 | ________________ 526 | ________________ 527 | //new Frame 528 | ________________ 529 | ________________ 530 | ________________ 531 | ________________ 532 | ________________ 533 | _____MMMMM______ 534 | _____MM_________ 535 | _____MMMMM______ 536 | _________MM_____ 537 | _________MM_____ 538 | _____MM__MM_____ 539 | ______MMMM______ 540 | ________________ 541 | ________________ 542 | ________________ 543 | ________________ 544 | //new Frame 545 | ________________ 546 | ________________ 547 | ________________ 548 | ________________ 549 | ________________ 550 | ______MMMM______ 551 | _____MM__MM_____ 552 | _____MM_________ 553 | _____MMMMM______ 554 | _____MM__MM_____ 555 | _____MM__MM_____ 556 | ______MMMM______ 557 | ________________ 558 | ________________ 559 | ________________ 560 | ________________ 561 | //new Frame 562 | ________________ 563 | ________________ 564 | ________________ 565 | ________________ 566 | ________________ 567 | _____MMMMMM_____ 568 | _____MM__MM_____ 569 | ________MM______ 570 | _______MM_______ 571 | _______MM_______ 572 | _______MM_______ 573 | _______MM_______ 574 | ________________ 575 | ________________ 576 | ________________ 577 | ________________ 578 | //new Frame 579 | ________________ 580 | ________________ 581 | ________________ 582 | ________________ 583 | ________________ 584 | ______MMMM______ 585 | _____MM__MM_____ 586 | _____MMM_MM_____ 587 | ______MMMM______ 588 | _____MM_MMM_____ 589 | _____MM__MM_____ 590 | ______MMMM______ 591 | ________________ 592 | ________________ 593 | ________________ 594 | ________________ 595 | //new Frame 596 | ________________ 597 | ________________ 598 | ________________ 599 | ________________ 600 | ________________ 601 | ______MMMM______ 602 | _____MM__MM_____ 603 | _____MM__MM_____ 604 | ______MMMMM_____ 605 | _________MM_____ 606 | _____MM__MM_____ 607 | ______MMMM______ 608 | ________________ 609 | ________________ 610 | ________________ 611 | ________________ 612 | //new Frame 613 | ________________ 614 | ________________ 615 | ________________ 616 | ________________ 617 | ________________ 618 | _______MMM______ 619 | _______MMM______ 620 | ______MMM_______ 621 | ______MM________ 622 | ______M_________ 623 | ________________ 624 | _____M__________ 625 | ________________ 626 | ________________ 627 | ________________ 628 | ________________ 629 | //new Frame 630 | ________________ 631 | ________________ 632 | ________________ 633 | ________________ 634 | ________________ 635 | ______MMMM______ 636 | _____MM__MM_____ 637 | _________MM_____ 638 | _______MMM______ 639 | _______M________ 640 | ________________ 641 | _______M________ 642 | ________________ 643 | ________________ 644 | ________________ 645 | ________________ 646 | //new Frame 647 | ________________ 648 | ________________ 649 | ________________ 650 | ________________ 651 | ________________ 652 | ________________ 653 | ______M__M______ 654 | _____MMMMMM_____ 655 | ______M__M______ 656 | ______M__M______ 657 | _____MMMMMM_____ 658 | ______M__M______ 659 | ________________ 660 | ________________ 661 | ________________ 662 | ________________ 663 | //new Frame 664 | ________________ 665 | ________________ 666 | ________________ 667 | ________________ 668 | ________________ 669 | ________________ 670 | ________________ 671 | ________________ 672 | ________________ 673 | ________________ 674 | ________________ 675 | ________________ 676 | ________________ 677 | ________________ 678 | ________________ 679 | ________________ 680 | //new Frame 681 | ________________ 682 | ________________ 683 | ________________ 684 | ________________ 685 | ________________ 686 | _____MM_________ 687 | _____MM_________ 688 | ________________ 689 | ________________ 690 | _____MM_________ 691 | _____MM_________ 692 | ________________ 693 | ________________ 694 | ________________ 695 | ________________ 696 | ________________ 697 | //new Frame 698 | ________________ 699 | ________________ 700 | ________________ 701 | ________________ 702 | ________________ 703 | ________________ 704 | ________________ 705 | ________________ 706 | ________________ 707 | _____MM_________ 708 | _____MM_________ 709 | _____M__________ 710 | ____M___________ 711 | ________________ 712 | ________________ 713 | ________________ 714 | //new Frame 715 | ________________ 716 | ________________ 717 | ________________ 718 | ________________ 719 | ________________ 720 | ________________ 721 | ________________ 722 | ________________ 723 | ________________ 724 | _____MM_________ 725 | _____MM_________ 726 | ________________ 727 | ________________ 728 | ________________ 729 | ________________ 730 | ________________ 731 | //new Frame 732 | ________________ 733 | ________________ 734 | ________________ 735 | ________________ 736 | ________________ 737 | _____MM_________ 738 | _____MM_________ 739 | _____M__________ 740 | ____M___________ 741 | ________________ 742 | ________________ 743 | ________________ 744 | ________________ 745 | ________________ 746 | ________________ 747 | ________________ 748 | 749 | //new Frame 750 | ________________ 751 | ________________ 752 | ________________ 753 | ________________ 754 | ________________ 755 | ________________ 756 | _______M________ 757 | _______M________ 758 | _____MMMMM______ 759 | _______M________ 760 | _______M________ 761 | ________________ 762 | ________________ 763 | ________________ 764 | ________________ 765 | ________________ 766 | //new Frame 767 | ________________ 768 | ________________ 769 | ________________ 770 | ________________ 771 | ________________ 772 | _______MM_______ 773 | ______M_________ 774 | ______M_________ 775 | ______M_________ 776 | ______M_________ 777 | ______M_________ 778 | _______MM_______ 779 | ________________ 780 | ________________ 781 | ________________ 782 | ________________ 783 | //new Frame 784 | ________________ 785 | ________________ 786 | ________________ 787 | ________________ 788 | ________________ 789 | _______MM_______ 790 | _________M______ 791 | _________M______ 792 | _________M______ 793 | _________M______ 794 | _________M______ 795 | _______MM_______ 796 | ________________ 797 | ________________ 798 | ________________ 799 | ________________ 800 | //new Frame 801 | ________________ 802 | ________________ 803 | ________________ 804 | ________________ 805 | ________________ 806 | ________________ 807 | _________M______ 808 | _________MM_____ 809 | _____MMMMMMM____ 810 | _________MM_____ 811 | _________M______ 812 | ________________ 813 | ________________ 814 | ________________ 815 | ________________ 816 | ________________ 817 | //new Frame 818 | ________________ 819 | ________________ 820 | ________________ 821 | ________________ 822 | ________________ 823 | ________________ 824 | _______M________ 825 | ______MM________ 826 | _____MMMMMMM____ 827 | ______MM________ 828 | _______M________ 829 | ________________ 830 | ________________ 831 | ________________ 832 | ________________ 833 | ________________ 834 | Animation: 835 | 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,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48 -------------------------------------------------------------------------------- /lib/jsfxr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SfxrParams 3 | * 4 | * Copyright 2010 Thomas Vian 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @author Thomas Vian 19 | */ 20 | 21 | /* eslint-disable */ 22 | 23 | /** @constructor */ 24 | function SfxrParams() { 25 | //-------------------------------------------------------------------------- 26 | // 27 | // Settings String Methods 28 | // 29 | //-------------------------------------------------------------------------- 30 | 31 | /** 32 | * Parses a settings array into the parameters 33 | * @param array Array of the settings values, where elements 0 - 23 are 34 | * a: waveType 35 | * b: attackTime 36 | * c: sustainTime 37 | * d: sustainPunch 38 | * e: decayTime 39 | * f: startFrequency 40 | * g: minFrequency 41 | * h: slide 42 | * i: deltaSlide 43 | * j: vibratoDepth 44 | * k: vibratoSpeed 45 | * l: changeAmount 46 | * m: changeSpeed 47 | * n: squareDuty 48 | * o: dutySweep 49 | * p: repeatSpeed 50 | * q: phaserOffset 51 | * r: phaserSweep 52 | * s: lpFilterCutoff 53 | * t: lpFilterCutoffSweep 54 | * u: lpFilterResonance 55 | * v: hpFilterCutoff 56 | * w: hpFilterCutoffSweep 57 | * x: masterVolume 58 | * @return If the string successfully parsed 59 | */ 60 | this.ss = function(values) 61 | { 62 | for ( var i = 0; i < 24; i++ ) 63 | { 64 | this[String.fromCharCode( 97 + i )] = values[i] || 0; 65 | } 66 | 67 | // I moved this here from the r(true) function 68 | if (this['c'] < .01) { 69 | this['c'] = .01; 70 | } 71 | 72 | var totalTime = this['b'] + this['c'] + this['e']; 73 | if (totalTime < .18) { 74 | var multiplier = .18 / totalTime; 75 | this['b'] *= multiplier; 76 | this['c'] *= multiplier; 77 | this['e'] *= multiplier; 78 | } 79 | } 80 | } 81 | 82 | /** 83 | * SfxrSynth 84 | * 85 | * Copyright 2010 Thomas Vian 86 | * 87 | * Licensed under the Apache License, Version 2.0 (the "License"); 88 | * you may not use this file except in compliance with the License. 89 | * You may obtain a copy of the License at 90 | * 91 | * http://www.apache.org/licenses/LICENSE-2.0 92 | * 93 | * Unless required by applicable law or agreed to in writing, software 94 | * distributed under the License is distributed on an "AS IS" BASIS, 95 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 96 | * See the License for the specific language governing permissions and 97 | * limitations under the License. 98 | * 99 | * @author Thomas Vian 100 | */ 101 | /** @constructor */ 102 | function SfxrSynth() { 103 | // All variables are kept alive through function closures 104 | 105 | //-------------------------------------------------------------------------- 106 | // 107 | // Sound Parameters 108 | // 109 | //-------------------------------------------------------------------------- 110 | 111 | this._p = new SfxrParams(); // Params instance 112 | 113 | //-------------------------------------------------------------------------- 114 | // 115 | // Synth Variables 116 | // 117 | //-------------------------------------------------------------------------- 118 | 119 | var _envelopeLength0, // Length of the attack stage 120 | _envelopeLength1, // Length of the sustain stage 121 | _envelopeLength2, // Length of the decay stage 122 | 123 | _period, // Period of the wave 124 | _maxPeriod, // Maximum period before sound stops (from minFrequency) 125 | 126 | _slide, // Note slide 127 | _deltaSlide, // Change in slide 128 | 129 | _changeAmount, // Amount to change the note by 130 | _changeTime, // Counter for the note change 131 | _changeLimit, // Once the time reaches this limit, the note changes 132 | 133 | _squareDuty, // Offset of center switching point in the square wave 134 | _dutySweep; // Amount to change the duty by 135 | 136 | //-------------------------------------------------------------------------- 137 | // 138 | // Synth Methods 139 | // 140 | //-------------------------------------------------------------------------- 141 | 142 | /** 143 | * rs the runing variables from the params 144 | * Used once at the start (total r) and for the repeat effect (partial r) 145 | */ 146 | this.r = function() { 147 | // Shorter reference 148 | var p = this._p; 149 | 150 | _period = 100 / (p['f'] * p['f'] + .001); 151 | _maxPeriod = 100 / (p['g'] * p['g'] + .001); 152 | 153 | _slide = 1 - p['h'] * p['h'] * p['h'] * .01; 154 | _deltaSlide = -p['i'] * p['i'] * p['i'] * .000001; 155 | 156 | if (!p['a']) { 157 | _squareDuty = .5 - p['n'] / 2; 158 | _dutySweep = -p['o'] * .00005; 159 | } 160 | 161 | _changeAmount = 1 + p['l'] * p['l'] * (p['l'] > 0 ? -.9 : 10); 162 | _changeTime = 0; 163 | _changeLimit = p['m'] == 1 ? 0 : (1 - p['m']) * (1 - p['m']) * 20000 + 32; 164 | } 165 | 166 | // I split the r() function into two functions for better readability 167 | this.tr = function() { 168 | this.r(); 169 | 170 | // Shorter reference 171 | var p = this._p; 172 | 173 | // Calculating the length is all that remained here, everything else moved somewhere 174 | _envelopeLength0 = p['b'] * p['b'] * 100000; 175 | _envelopeLength1 = p['c'] * p['c'] * 100000; 176 | _envelopeLength2 = p['e'] * p['e'] * 100000 + 12; 177 | // Full length of the volume envelop (and therefore sound) 178 | // Make sure the length can be divided by 3 so we will not need the padding "==" after base64 encode 179 | return ((_envelopeLength0 + _envelopeLength1 + _envelopeLength2) / 3 | 0) * 3; 180 | } 181 | 182 | /** 183 | * Writes the wave to the supplied buffer ByteArray 184 | * @param buffer A ByteArray to write the wave to 185 | * @return If the wave is finished 186 | */ 187 | this.sw = function(buffer, length) { 188 | // Shorter reference 189 | var p = this._p; 190 | 191 | // If the filters are active 192 | var _filters = p['s'] != 1 || p['v'], 193 | // Cutoff multiplier which adjusts the amount the wave position can move 194 | _hpFilterCutoff = p['v'] * p['v'] * .1, 195 | // Speed of the high-pass cutoff multiplier 196 | _hpFilterDeltaCutoff = 1 + p['w'] * .0003, 197 | // Cutoff multiplier which adjusts the amount the wave position can move 198 | _lpFilterCutoff = p['s'] * p['s'] * p['s'] * .1, 199 | // Speed of the low-pass cutoff multiplier 200 | _lpFilterDeltaCutoff = 1 + p['t'] * .0001, 201 | // If the low pass filter is active 202 | _lpFilterOn = p['s'] != 1, 203 | // masterVolume * masterVolume (for quick calculations) 204 | _masterVolume = p['x'] * p['x'], 205 | // Minimum frequency before stopping 206 | _minFreqency = p['g'], 207 | // If the phaser is active 208 | _phaser = p['q'] || p['r'], 209 | // Change in phase offset 210 | _phaserDeltaOffset = p['r'] * p['r'] * p['r'] * .2, 211 | // Phase offset for phaser effect 212 | _phaserOffset = p['q'] * p['q'] * (p['q'] < 0 ? -1020 : 1020), 213 | // Once the time reaches this limit, some of the iables are r 214 | _repeatLimit = p['p'] ? ((1 - p['p']) * (1 - p['p']) * 20000 | 0) + 32 : 0, 215 | // The punch factor (louder at begining of sustain) 216 | _sustainPunch = p['d'], 217 | // Amount to change the period of the wave by at the peak of the vibrato wave 218 | _vibratoAmplitude = p['j'] / 2, 219 | // Speed at which the vibrato phase moves 220 | _vibratoSpeed = p['k'] * p['k'] * .01, 221 | // The type of wave to generate 222 | _waveType = p['a']; 223 | 224 | var _envelopeLength = _envelopeLength0, // Length of the current envelope stage 225 | _envelopeOverLength0 = 1 / _envelopeLength0, // (for quick calculations) 226 | _envelopeOverLength1 = 1 / _envelopeLength1, // (for quick calculations) 227 | _envelopeOverLength2 = 1 / _envelopeLength2; // (for quick calculations) 228 | 229 | // Damping muliplier which restricts how fast the wave position can move 230 | var _lpFilterDamping = 5 / (1 + p['u'] * p['u'] * 20) * (.01 + _lpFilterCutoff); 231 | if (_lpFilterDamping > .8) { 232 | _lpFilterDamping = .8; 233 | } 234 | _lpFilterDamping = 1 - _lpFilterDamping; 235 | 236 | var _finished = false, // If the sound has finished 237 | _envelopeStage = 0, // Current stage of the envelope (attack, sustain, decay, end) 238 | _envelopeTime = 0, // Current time through current enelope stage 239 | _envelopeVolume = 0, // Current volume of the envelope 240 | _hpFilterPos = 0, // Adjusted wave position after high-pass filter 241 | _lpFilterDeltaPos = 0, // Change in low-pass wave position, as allowed by the cutoff and damping 242 | _lpFilterOldPos, // Previous low-pass wave position 243 | _lpFilterPos = 0, // Adjusted wave position after low-pass filter 244 | _periodTemp, // Period modified by vibrato 245 | _phase = 0, // Phase through the wave 246 | _phaserInt, // Integer phaser offset, for bit maths 247 | _phaserPos = 0, // Position through the phaser buffer 248 | _pos, // Phase expresed as a Number from 0-1, used for fast sin approx 249 | _repeatTime = 0, // Counter for the repeats 250 | _sample, // Sub-sample calculated 8 times per actual sample, averaged out to get the super sample 251 | _superSample, // Actual sample writen to the wave 252 | _vibratoPhase = 0; // Phase through the vibrato sine wave 253 | 254 | // Buffer of wave values used to create the out of phase second wave 255 | var _phaserBuffer = new Array(1024), 256 | // Buffer of random values used to generate noise 257 | _noiseBuffer = new Array(32); 258 | for (var i = _phaserBuffer.length; i--; ) { 259 | _phaserBuffer[i] = 0; 260 | } 261 | for (var i = _noiseBuffer.length; i--; ) { 262 | _noiseBuffer[i] = getRandomValue(2,-1); 263 | } 264 | 265 | for (var i = 0; i < length; i++) { 266 | if (_finished) { 267 | return i; 268 | } 269 | 270 | // Repeats every _repeatLimit times, partially rting the sound parameters 271 | if (_repeatLimit) { 272 | if (++_repeatTime >= _repeatLimit) { 273 | _repeatTime = 0; 274 | this.r(); 275 | } 276 | } 277 | 278 | // If _changeLimit is reached, shifts the pitch 279 | if (_changeLimit) { 280 | if (++_changeTime >= _changeLimit) { 281 | _changeLimit = 0; 282 | _period *= _changeAmount; 283 | } 284 | } 285 | 286 | // Acccelerate and apply slide 287 | _slide += _deltaSlide; 288 | _period *= _slide; 289 | 290 | // Checks for frequency getting too low, and stops the sound if a minFrequency was set 291 | if (_period > _maxPeriod) { 292 | _period = _maxPeriod; 293 | if (_minFreqency > 0) { 294 | _finished = true; 295 | } 296 | } 297 | 298 | _periodTemp = _period; 299 | 300 | // Applies the vibrato effect 301 | if (_vibratoAmplitude > 0) { 302 | _vibratoPhase += _vibratoSpeed; 303 | _periodTemp *= 1 + Math.sin(_vibratoPhase) * _vibratoAmplitude; 304 | } 305 | 306 | _periodTemp |= 0; 307 | if (_periodTemp < 8) { 308 | _periodTemp = 8; 309 | } 310 | 311 | // Sweeps the square duty 312 | if (!_waveType) { 313 | _squareDuty += _dutySweep; 314 | if (_squareDuty < 0) { 315 | _squareDuty = 0; 316 | } else if (_squareDuty > .5) { 317 | _squareDuty = .5; 318 | } 319 | } 320 | 321 | // Moves through the different stages of the volume envelope 322 | if (++_envelopeTime > _envelopeLength) { 323 | _envelopeTime = 0; 324 | 325 | switch (++_envelopeStage) { 326 | case 1: 327 | _envelopeLength = _envelopeLength1; 328 | break; 329 | case 2: 330 | _envelopeLength = _envelopeLength2; 331 | } 332 | } 333 | 334 | // Sets the volume based on the position in the envelope 335 | switch (_envelopeStage) { 336 | case 0: 337 | _envelopeVolume = _envelopeTime * _envelopeOverLength0; 338 | break; 339 | case 1: 340 | _envelopeVolume = 1 + (1 - _envelopeTime * _envelopeOverLength1) * 2 * _sustainPunch; 341 | break; 342 | case 2: 343 | _envelopeVolume = 1 - _envelopeTime * _envelopeOverLength2; 344 | break; 345 | case 3: 346 | _envelopeVolume = 0; 347 | _finished = true; 348 | } 349 | 350 | // Moves the phaser offset 351 | if (_phaser) { 352 | _phaserOffset += _phaserDeltaOffset; 353 | _phaserInt = _phaserOffset | 0; 354 | if (_phaserInt < 0) { 355 | _phaserInt = -_phaserInt; 356 | } else if (_phaserInt > 1023) { 357 | _phaserInt = 1023; 358 | } 359 | } 360 | 361 | // Moves the high-pass filter cutoff 362 | if (_filters && _hpFilterDeltaCutoff) { 363 | _hpFilterCutoff *= _hpFilterDeltaCutoff; 364 | if (_hpFilterCutoff < .00001) { 365 | _hpFilterCutoff = .00001; 366 | } else if (_hpFilterCutoff > .1) { 367 | _hpFilterCutoff = .1; 368 | } 369 | } 370 | 371 | _superSample = 0; 372 | for (var j = 8; j--; ) { 373 | // Cycles through the period 374 | _phase++; 375 | if (_phase >= _periodTemp) { 376 | _phase %= _periodTemp; 377 | 378 | // Generates new random noise for this period 379 | if (_waveType == 3) { 380 | for (var n = _noiseBuffer.length; n--; ) { 381 | _noiseBuffer[n] = getRandomValue(2,-1); 382 | } 383 | } 384 | } 385 | 386 | // Gets the sample from the oscillator 387 | switch (_waveType) { 388 | case 0: // Square wave 389 | _sample = ((_phase / _periodTemp) < _squareDuty) ? .5 : -.5; 390 | break; 391 | case 1: // Saw wave 392 | _sample = 1 - _phase / _periodTemp * 2; 393 | break; 394 | case 2: // Sine wave (fast and accurate approx) 395 | _pos = _phase / _periodTemp; 396 | _pos = (_pos > .5 ? _pos - 1 : _pos) * 6.28318531; 397 | _sample = 1.27323954 * _pos + .405284735 * _pos * _pos * (_pos < 0 ? 1 : -1); 398 | _sample = .225 * ((_sample < 0 ? -1 : 1) * _sample * _sample - _sample) + _sample; 399 | break; 400 | case 3: // Noise 401 | _sample = _noiseBuffer[Math.abs(_phase * 32 / _periodTemp | 0)]; 402 | } 403 | 404 | // Applies the low and high pass filters 405 | if (_filters) { 406 | _lpFilterOldPos = _lpFilterPos; 407 | _lpFilterCutoff *= _lpFilterDeltaCutoff; 408 | if (_lpFilterCutoff < 0) { 409 | _lpFilterCutoff = 0; 410 | } else if (_lpFilterCutoff > .1) { 411 | _lpFilterCutoff = .1; 412 | } 413 | 414 | if (_lpFilterOn) { 415 | _lpFilterDeltaPos += (_sample - _lpFilterPos) * _lpFilterCutoff; 416 | _lpFilterDeltaPos *= _lpFilterDamping; 417 | } else { 418 | _lpFilterPos = _sample; 419 | _lpFilterDeltaPos = 0; 420 | } 421 | 422 | _lpFilterPos += _lpFilterDeltaPos; 423 | 424 | _hpFilterPos += _lpFilterPos - _lpFilterOldPos; 425 | _hpFilterPos *= 1 - _hpFilterCutoff; 426 | _sample = _hpFilterPos; 427 | } 428 | 429 | // Applies the phaser effect 430 | if (_phaser) { 431 | _phaserBuffer[_phaserPos % 1024] = _sample; 432 | _sample += _phaserBuffer[(_phaserPos - _phaserInt + 1024) % 1024]; 433 | _phaserPos++; 434 | } 435 | 436 | _superSample += _sample; 437 | } 438 | 439 | // Averages out the super samples and applies volumes 440 | _superSample *= .125 * _envelopeVolume * _masterVolume; 441 | 442 | // Clipping if too loud 443 | buffer[i] = _superSample >= 1 ? 32767 : _superSample <= -1 ? -32768 : _superSample * 32767 | 0; 444 | } 445 | 446 | return length; 447 | } 448 | } 449 | 450 | // Adapted from http://codebase.es/riffwave/ 451 | var synth = new SfxrSynth(); 452 | // Export for the Closure Compiler 453 | function jsfxr (settings, audioCtx, cb) { 454 | // Initialize SfxrParams 455 | synth._p.ss(settings); 456 | // Synthesize Wave 457 | var envelopeFullLength = synth.tr(); 458 | var data = new Uint8Array(((envelopeFullLength + 1) / 2 | 0) * 4 + 44); 459 | 460 | var used = synth.sw(new Uint16Array(data.buffer, 44), envelopeFullLength) * 2; 461 | 462 | var dv = new Uint32Array(data.buffer, 0, 44); 463 | // Initialize header 464 | dv[0] = 0x46464952; // "RIFF" 465 | dv[1] = used + 36; // put total size here 466 | dv[2] = 0x45564157; // "WAVE" 467 | dv[3] = 0x20746D66; // "fmt " 468 | dv[4] = 0x00000010; // size of the following 469 | dv[5] = 0x00010001; // Mono: 1 channel, PCM format 470 | dv[6] = 0x0000AC44; // 44,100 samples per second 471 | dv[7] = 0x00015888; // byte rate: two bytes per sample 472 | dv[8] = 0x00100002; // 16 bits per sample, aligned on every two bytes 473 | dv[9] = 0x61746164; // "data" 474 | dv[10] = used; // put number of samples here 475 | 476 | // Base64 encoding written by me, @maettig 477 | used += 44; 478 | var i = 0, 479 | base64Characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', 480 | output = 'data:audio/wav;base64,'; 481 | for (; i < used; i += 3) 482 | { 483 | var a = data[i] << 16 | data[i + 1] << 8 | data[i + 2]; 484 | output += base64Characters[a >> 18] + base64Characters[a >> 12 & 63] + base64Characters[a >> 6 & 63] + base64Characters[a & 63]; 485 | } 486 | 487 | audioCtx && audioCtx.decodeAudioData(data.buffer, cb); 488 | 489 | return output; 490 | } 491 | --------------------------------------------------------------------------------