├── img ├── background.png └── warrior │ ├── Attack1.png │ ├── Attack2.png │ ├── Attack3.png │ ├── Death.png │ ├── Fall.png │ ├── FallLeft.png │ ├── Idle.png │ ├── IdleLeft.png │ ├── Jump.png │ ├── JumpLeft.png │ ├── Run.png │ ├── RunLeft.png │ ├── Take Hit - white silhouette.png │ └── Take Hit.png ├── index.html ├── index.js └── js ├── classes ├── CollisionBlock.js ├── Player.js └── Sprite.js ├── data └── collisions.js └── utils.js /img/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/background.png -------------------------------------------------------------------------------- /img/warrior/Attack1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/Attack1.png -------------------------------------------------------------------------------- /img/warrior/Attack2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/Attack2.png -------------------------------------------------------------------------------- /img/warrior/Attack3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/Attack3.png -------------------------------------------------------------------------------- /img/warrior/Death.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/Death.png -------------------------------------------------------------------------------- /img/warrior/Fall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/Fall.png -------------------------------------------------------------------------------- /img/warrior/FallLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/FallLeft.png -------------------------------------------------------------------------------- /img/warrior/Idle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/Idle.png -------------------------------------------------------------------------------- /img/warrior/IdleLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/IdleLeft.png -------------------------------------------------------------------------------- /img/warrior/Jump.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/Jump.png -------------------------------------------------------------------------------- /img/warrior/JumpLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/JumpLeft.png -------------------------------------------------------------------------------- /img/warrior/Run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/Run.png -------------------------------------------------------------------------------- /img/warrior/RunLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/RunLeft.png -------------------------------------------------------------------------------- /img/warrior/Take Hit - white silhouette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/Take Hit - white silhouette.png -------------------------------------------------------------------------------- /img/warrior/Take Hit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscourses/vertical-platformer/fa3d460de134ae395eab4b2c5100fdb4a96a5bca/img/warrior/Take Hit.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const canvas = document.querySelector('canvas') 2 | const c = canvas.getContext('2d') 3 | 4 | canvas.width = 1024 5 | canvas.height = 576 6 | 7 | const scaledCanvas = { 8 | width: canvas.width / 4, 9 | height: canvas.height / 4, 10 | } 11 | 12 | const floorCollisions2D = [] 13 | for (let i = 0; i < floorCollisions.length; i += 36) { 14 | floorCollisions2D.push(floorCollisions.slice(i, i + 36)) 15 | } 16 | 17 | const collisionBlocks = [] 18 | floorCollisions2D.forEach((row, y) => { 19 | row.forEach((symbol, x) => { 20 | if (symbol === 202) { 21 | collisionBlocks.push( 22 | new CollisionBlock({ 23 | position: { 24 | x: x * 16, 25 | y: y * 16, 26 | }, 27 | }) 28 | ) 29 | } 30 | }) 31 | }) 32 | 33 | const platformCollisions2D = [] 34 | for (let i = 0; i < platformCollisions.length; i += 36) { 35 | platformCollisions2D.push(platformCollisions.slice(i, i + 36)) 36 | } 37 | 38 | const platformCollisionBlocks = [] 39 | platformCollisions2D.forEach((row, y) => { 40 | row.forEach((symbol, x) => { 41 | if (symbol === 202) { 42 | platformCollisionBlocks.push( 43 | new CollisionBlock({ 44 | position: { 45 | x: x * 16, 46 | y: y * 16, 47 | }, 48 | height: 4, 49 | }) 50 | ) 51 | } 52 | }) 53 | }) 54 | 55 | const gravity = 0.1 56 | 57 | const player = new Player({ 58 | position: { 59 | x: 100, 60 | y: 300, 61 | }, 62 | collisionBlocks, 63 | platformCollisionBlocks, 64 | imageSrc: './img/warrior/Idle.png', 65 | frameRate: 8, 66 | animations: { 67 | Idle: { 68 | imageSrc: './img/warrior/Idle.png', 69 | frameRate: 8, 70 | frameBuffer: 3, 71 | }, 72 | Run: { 73 | imageSrc: './img/warrior/Run.png', 74 | frameRate: 8, 75 | frameBuffer: 5, 76 | }, 77 | Jump: { 78 | imageSrc: './img/warrior/Jump.png', 79 | frameRate: 2, 80 | frameBuffer: 3, 81 | }, 82 | Fall: { 83 | imageSrc: './img/warrior/Fall.png', 84 | frameRate: 2, 85 | frameBuffer: 3, 86 | }, 87 | FallLeft: { 88 | imageSrc: './img/warrior/FallLeft.png', 89 | frameRate: 2, 90 | frameBuffer: 3, 91 | }, 92 | RunLeft: { 93 | imageSrc: './img/warrior/RunLeft.png', 94 | frameRate: 8, 95 | frameBuffer: 5, 96 | }, 97 | IdleLeft: { 98 | imageSrc: './img/warrior/IdleLeft.png', 99 | frameRate: 8, 100 | frameBuffer: 3, 101 | }, 102 | JumpLeft: { 103 | imageSrc: './img/warrior/JumpLeft.png', 104 | frameRate: 2, 105 | frameBuffer: 3, 106 | }, 107 | }, 108 | }) 109 | 110 | const keys = { 111 | d: { 112 | pressed: false, 113 | }, 114 | a: { 115 | pressed: false, 116 | }, 117 | } 118 | 119 | const background = new Sprite({ 120 | position: { 121 | x: 0, 122 | y: 0, 123 | }, 124 | imageSrc: './img/background.png', 125 | }) 126 | 127 | const backgroundImageHeight = 432 128 | 129 | const camera = { 130 | position: { 131 | x: 0, 132 | y: -backgroundImageHeight + scaledCanvas.height, 133 | }, 134 | } 135 | 136 | function animate() { 137 | window.requestAnimationFrame(animate) 138 | c.fillStyle = 'white' 139 | c.fillRect(0, 0, canvas.width, canvas.height) 140 | 141 | c.save() 142 | c.scale(4, 4) 143 | c.translate(camera.position.x, camera.position.y) 144 | background.update() 145 | // collisionBlocks.forEach((collisionBlock) => { 146 | // collisionBlock.update() 147 | // }) 148 | 149 | // platformCollisionBlocks.forEach((block) => { 150 | // block.update() 151 | // }) 152 | 153 | player.checkForHorizontalCanvasCollision() 154 | player.update() 155 | 156 | player.velocity.x = 0 157 | if (keys.d.pressed) { 158 | player.switchSprite('Run') 159 | player.velocity.x = 2 160 | player.lastDirection = 'right' 161 | player.shouldPanCameraToTheLeft({ canvas, camera }) 162 | } else if (keys.a.pressed) { 163 | player.switchSprite('RunLeft') 164 | player.velocity.x = -2 165 | player.lastDirection = 'left' 166 | player.shouldPanCameraToTheRight({ canvas, camera }) 167 | } else if (player.velocity.y === 0) { 168 | if (player.lastDirection === 'right') player.switchSprite('Idle') 169 | else player.switchSprite('IdleLeft') 170 | } 171 | 172 | if (player.velocity.y < 0) { 173 | player.shouldPanCameraDown({ camera, canvas }) 174 | if (player.lastDirection === 'right') player.switchSprite('Jump') 175 | else player.switchSprite('JumpLeft') 176 | } else if (player.velocity.y > 0) { 177 | player.shouldPanCameraUp({ camera, canvas }) 178 | if (player.lastDirection === 'right') player.switchSprite('Fall') 179 | else player.switchSprite('FallLeft') 180 | } 181 | 182 | c.restore() 183 | } 184 | 185 | animate() 186 | 187 | window.addEventListener('keydown', (event) => { 188 | switch (event.key) { 189 | case 'd': 190 | keys.d.pressed = true 191 | break 192 | case 'a': 193 | keys.a.pressed = true 194 | break 195 | case 'w': 196 | player.velocity.y = -4 197 | break 198 | } 199 | }) 200 | 201 | window.addEventListener('keyup', (event) => { 202 | switch (event.key) { 203 | case 'd': 204 | keys.d.pressed = false 205 | break 206 | case 'a': 207 | keys.a.pressed = false 208 | break 209 | } 210 | }) 211 | -------------------------------------------------------------------------------- /js/classes/CollisionBlock.js: -------------------------------------------------------------------------------- 1 | class CollisionBlock { 2 | constructor({ position, height = 16 }) { 3 | this.position = position 4 | this.width = 16 5 | this.height = height 6 | } 7 | 8 | draw() { 9 | c.fillStyle = 'rgba(255, 0, 0, 0.5)' 10 | c.fillRect(this.position.x, this.position.y, this.width, this.height) 11 | } 12 | 13 | update() { 14 | this.draw() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /js/classes/Player.js: -------------------------------------------------------------------------------- 1 | class Player extends Sprite { 2 | constructor({ 3 | position, 4 | collisionBlocks, 5 | platformCollisionBlocks, 6 | imageSrc, 7 | frameRate, 8 | scale = 0.5, 9 | animations, 10 | }) { 11 | super({ imageSrc, frameRate, scale }) 12 | this.position = position 13 | this.velocity = { 14 | x: 0, 15 | y: 1, 16 | } 17 | 18 | this.collisionBlocks = collisionBlocks 19 | this.platformCollisionBlocks = platformCollisionBlocks 20 | this.hitbox = { 21 | position: { 22 | x: this.position.x, 23 | y: this.position.y, 24 | }, 25 | width: 10, 26 | height: 10, 27 | } 28 | 29 | this.animations = animations 30 | this.lastDirection = 'right' 31 | 32 | for (let key in this.animations) { 33 | const image = new Image() 34 | image.src = this.animations[key].imageSrc 35 | 36 | this.animations[key].image = image 37 | } 38 | 39 | this.camerabox = { 40 | position: { 41 | x: this.position.x, 42 | y: this.position.y, 43 | }, 44 | width: 200, 45 | height: 80, 46 | } 47 | } 48 | 49 | switchSprite(key) { 50 | if (this.image === this.animations[key].image || !this.loaded) return 51 | 52 | this.currentFrame = 0 53 | this.image = this.animations[key].image 54 | this.frameBuffer = this.animations[key].frameBuffer 55 | this.frameRate = this.animations[key].frameRate 56 | } 57 | 58 | updateCamerabox() { 59 | this.camerabox = { 60 | position: { 61 | x: this.position.x - 50, 62 | y: this.position.y, 63 | }, 64 | width: 200, 65 | height: 80, 66 | } 67 | } 68 | 69 | checkForHorizontalCanvasCollision() { 70 | if ( 71 | this.hitbox.position.x + this.hitbox.width + this.velocity.x >= 576 || 72 | this.hitbox.position.x + this.velocity.x <= 0 73 | ) { 74 | this.velocity.x = 0 75 | } 76 | } 77 | 78 | shouldPanCameraToTheLeft({ canvas, camera }) { 79 | const cameraboxRightSide = this.camerabox.position.x + this.camerabox.width 80 | const scaledDownCanvasWidth = canvas.width / 4 81 | 82 | if (cameraboxRightSide >= 576) return 83 | 84 | if ( 85 | cameraboxRightSide >= 86 | scaledDownCanvasWidth + Math.abs(camera.position.x) 87 | ) { 88 | camera.position.x -= this.velocity.x 89 | } 90 | } 91 | 92 | shouldPanCameraToTheRight({ canvas, camera }) { 93 | if (this.camerabox.position.x <= 0) return 94 | 95 | if (this.camerabox.position.x <= Math.abs(camera.position.x)) { 96 | camera.position.x -= this.velocity.x 97 | } 98 | } 99 | 100 | shouldPanCameraDown({ canvas, camera }) { 101 | if (this.camerabox.position.y + this.velocity.y <= 0) return 102 | 103 | if (this.camerabox.position.y <= Math.abs(camera.position.y)) { 104 | camera.position.y -= this.velocity.y 105 | } 106 | } 107 | 108 | shouldPanCameraUp({ canvas, camera }) { 109 | if ( 110 | this.camerabox.position.y + this.camerabox.height + this.velocity.y >= 111 | 432 112 | ) 113 | return 114 | 115 | const scaledCanvasHeight = canvas.height / 4 116 | 117 | if ( 118 | this.camerabox.position.y + this.camerabox.height >= 119 | Math.abs(camera.position.y) + scaledCanvasHeight 120 | ) { 121 | camera.position.y -= this.velocity.y 122 | } 123 | } 124 | 125 | update() { 126 | this.updateFrames() 127 | this.updateHitbox() 128 | 129 | this.updateCamerabox() 130 | // c.fillStyle = 'rgba(0, 0, 255, 0.2)' 131 | // c.fillRect( 132 | // this.camerabox.position.x, 133 | // this.camerabox.position.y, 134 | // this.camerabox.width, 135 | // this.camerabox.height 136 | // ) 137 | 138 | // draws out the image 139 | // c.fillStyle = 'rgba(0, 255, 0, 0.2)' 140 | // c.fillRect(this.position.x, this.position.y, this.width, this.height) 141 | 142 | // c.fillStyle = 'rgba(255, 0, 0, 0.2)' 143 | // c.fillRect( 144 | // this.hitbox.position.x, 145 | // this.hitbox.position.y, 146 | // this.hitbox.width, 147 | // this.hitbox.height 148 | // ) 149 | 150 | this.draw() 151 | 152 | this.position.x += this.velocity.x 153 | this.updateHitbox() 154 | this.checkForHorizontalCollisions() 155 | this.applyGravity() 156 | this.updateHitbox() 157 | this.checkForVerticalCollisions() 158 | } 159 | 160 | updateHitbox() { 161 | this.hitbox = { 162 | position: { 163 | x: this.position.x + 35, 164 | y: this.position.y + 26, 165 | }, 166 | width: 14, 167 | height: 27, 168 | } 169 | } 170 | 171 | checkForHorizontalCollisions() { 172 | for (let i = 0; i < this.collisionBlocks.length; i++) { 173 | const collisionBlock = this.collisionBlocks[i] 174 | 175 | if ( 176 | collision({ 177 | object1: this.hitbox, 178 | object2: collisionBlock, 179 | }) 180 | ) { 181 | if (this.velocity.x > 0) { 182 | this.velocity.x = 0 183 | 184 | const offset = 185 | this.hitbox.position.x - this.position.x + this.hitbox.width 186 | 187 | this.position.x = collisionBlock.position.x - offset - 0.01 188 | break 189 | } 190 | 191 | if (this.velocity.x < 0) { 192 | this.velocity.x = 0 193 | 194 | const offset = this.hitbox.position.x - this.position.x 195 | 196 | this.position.x = 197 | collisionBlock.position.x + collisionBlock.width - offset + 0.01 198 | break 199 | } 200 | } 201 | } 202 | } 203 | 204 | applyGravity() { 205 | this.velocity.y += gravity 206 | this.position.y += this.velocity.y 207 | } 208 | 209 | checkForVerticalCollisions() { 210 | for (let i = 0; i < this.collisionBlocks.length; i++) { 211 | const collisionBlock = this.collisionBlocks[i] 212 | 213 | if ( 214 | collision({ 215 | object1: this.hitbox, 216 | object2: collisionBlock, 217 | }) 218 | ) { 219 | if (this.velocity.y > 0) { 220 | this.velocity.y = 0 221 | 222 | const offset = 223 | this.hitbox.position.y - this.position.y + this.hitbox.height 224 | 225 | this.position.y = collisionBlock.position.y - offset - 0.01 226 | break 227 | } 228 | 229 | if (this.velocity.y < 0) { 230 | this.velocity.y = 0 231 | 232 | const offset = this.hitbox.position.y - this.position.y 233 | 234 | this.position.y = 235 | collisionBlock.position.y + collisionBlock.height - offset + 0.01 236 | break 237 | } 238 | } 239 | } 240 | 241 | // platform collision blocks 242 | for (let i = 0; i < this.platformCollisionBlocks.length; i++) { 243 | const platformCollisionBlock = this.platformCollisionBlocks[i] 244 | 245 | if ( 246 | platformCollision({ 247 | object1: this.hitbox, 248 | object2: platformCollisionBlock, 249 | }) 250 | ) { 251 | if (this.velocity.y > 0) { 252 | this.velocity.y = 0 253 | 254 | const offset = 255 | this.hitbox.position.y - this.position.y + this.hitbox.height 256 | 257 | this.position.y = platformCollisionBlock.position.y - offset - 0.01 258 | break 259 | } 260 | } 261 | } 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /js/classes/Sprite.js: -------------------------------------------------------------------------------- 1 | class Sprite { 2 | constructor({ 3 | position, 4 | imageSrc, 5 | frameRate = 1, 6 | frameBuffer = 3, 7 | scale = 1, 8 | }) { 9 | this.position = position 10 | this.scale = scale 11 | this.loaded = false 12 | this.image = new Image() 13 | this.image.onload = () => { 14 | this.width = (this.image.width / this.frameRate) * this.scale 15 | this.height = this.image.height * this.scale 16 | this.loaded = true 17 | } 18 | this.image.src = imageSrc 19 | this.frameRate = frameRate 20 | this.currentFrame = 0 21 | this.frameBuffer = frameBuffer 22 | this.elapsedFrames = 0 23 | } 24 | 25 | draw() { 26 | if (!this.image) return 27 | 28 | const cropbox = { 29 | position: { 30 | x: this.currentFrame * (this.image.width / this.frameRate), 31 | y: 0, 32 | }, 33 | width: this.image.width / this.frameRate, 34 | height: this.image.height, 35 | } 36 | 37 | c.drawImage( 38 | this.image, 39 | cropbox.position.x, 40 | cropbox.position.y, 41 | cropbox.width, 42 | cropbox.height, 43 | this.position.x, 44 | this.position.y, 45 | this.width, 46 | this.height 47 | ) 48 | } 49 | 50 | update() { 51 | this.draw() 52 | this.updateFrames() 53 | } 54 | 55 | updateFrames() { 56 | this.elapsedFrames++ 57 | 58 | if (this.elapsedFrames % this.frameBuffer === 0) { 59 | if (this.currentFrame < this.frameRate - 1) this.currentFrame++ 60 | else this.currentFrame = 0 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /js/data/collisions.js: -------------------------------------------------------------------------------- 1 | const floorCollisions = [ 2 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34 | 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 37 | 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 38 | 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, 39 | 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41 | ] 42 | 43 | const platformCollisions = [ 44 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 50 | 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 202, 51 | 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 53 | 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57 | 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 58 | 0, 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 62 | 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64 | 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 65 | 202, 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 68 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 70 | 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 72 | 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 202, 202, 202, 0, 0, 0, 0, 0, 0, 76 | 0, 0, 0, 202, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83 | ] 84 | -------------------------------------------------------------------------------- /js/utils.js: -------------------------------------------------------------------------------- 1 | function collision({ object1, object2 }) { 2 | return ( 3 | object1.position.y + object1.height >= object2.position.y && 4 | object1.position.y <= object2.position.y + object2.height && 5 | object1.position.x <= object2.position.x + object2.width && 6 | object1.position.x + object1.width >= object2.position.x 7 | ) 8 | } 9 | 10 | function platformCollision({ object1, object2 }) { 11 | return ( 12 | object1.position.y + object1.height >= object2.position.y && 13 | object1.position.y + object1.height <= 14 | object2.position.y + object2.height && 15 | object1.position.x <= object2.position.x + object2.width && 16 | object1.position.x + object1.width >= object2.position.x 17 | ) 18 | } 19 | --------------------------------------------------------------------------------