//------------------------------------------------------------------------- // 4. RENDERING //------------------------------------------------------------------------- function render(ctx, frame, dt, thiscurrentLevel) { // ? Kann ich mich eigentlich mit scale und translate noch weiter an Pico-8 orientieren und in den variables sowas wie scale = ctx.scale oder so erstellen? // * Disable Image Smoothing ctx.mozImageSmoothingEnabled = false ctx.webkitImageSmoothingEnabled = false ctx.msImageSmoothingEnabled = false ctx.imageSmoothingEnabled = false ctx.save() ctx.scale( Math.round(thiscurrentLevel.scalingFactor / 2), Math.round(thiscurrentLevel.scalingFactor / 2) ) ctx.clearRect(0, 0, width, height) renderCamera() //renderCameraWithBox() renderBackground(ctx, thiscurrentLevel.backgroundAtlas, bgCells) renderMap(ctx, thiscurrentLevel.levelAtlas, cells) renderPlayer(ctx, playerAtlas, dt, frame) renderBullets(ctx, itemsAtlas, dt, frame) renderMonsters(ctx, enemyAtlas, dt, frame) renderTreasure(ctx, itemsAtlas, dt, frame) renderPickups(ctx, itemsAtlas, dt, frame) renderForeground(ctx, thiscurrentLevel.foregroundAtlas, fgCells) renderLiquids(ctx, thiscurrentLevel.foregroundAtlas, fgCells) // * Draw CameraBox //renderCameraBox() ctx.restore() renderPause() renderHud(ctx, meterAtlas, dt, frame) renderHudSprites() //fadeScreen(frame, dt) renderDevInfos() } // Map Limit Variables // * Das hier ist die allgemeine Funktion um Tiles aus dem TileAtlas auf den Canvas zu malen. function drawTile(levelAtlas, cell, dx, dy, opacity) { levelAtlas.sourceY = Math.floor(cell / levelAtlas.atlasCol) * levelAtlas.tileSize levelAtlas.sourceX = (cell % levelAtlas.atlasCol) * levelAtlas.tileSize // ? Wofür stehen die Werte sWidth, sHeight, dWidth, dHeight ctx.globalAlpha = opacity // ! Kann ich die ganzen festen Zahlen als Variablen aus der Map holen? ctx.drawImage( levelAtlas.tileAtlas, levelAtlas.sourceX, levelAtlas.sourceY, 16, 16, dx * 16, dy * 16, 16, 16 ) } function renderBackground(ctx, levelAtlas) { var x, y, cell for (y = 0; y < mapHeight; y++) { for (x = 0; x < mapWidth; x++) { cell = bgTcell(x, y, mapWidth) if (cell) { drawTile(levelAtlas, cell - levelAtlas.offset, x, y) } } } } function renderForeground(ctx, levelAtlas) { var x, y, cell for (y = 0; y < mapHeight; y++) { for (x = 0; x < mapWidth; x++) { cell = fgTcell(x, y, mapWidth) if (cell) { drawTile(levelAtlas, cell - levelAtlas.offset, x, y) } } } } function renderLiquids(ctx, levelAtlas) { var x, y, cell for (y = 0; y < mapHeight; y++) { for (x = 0; x < mapWidth; x++) { cell = lqTcell(x, y, mapWidth) if (cell) { drawTile(levelAtlas, cell - levelAtlas.offset, x, y, 0.5) } } } } function renderMap(ctx, levelAtlas) { var x, y, cell for (y = 0; y < mapHeight; y++) { for (x = 0; x < mapWidth; x++) { cell = tcell(x, y, mapWidth) if (cell) { drawTile(levelAtlas, cell - levelAtlas.offset, x, y) } } } } // * Sprite Animation function drawSprite(entity, spriteAtlas, dt, frame) { /* entity.start.x === 48 && entity.start.y === 656 && console.log('log frame ', entity.sprites.idle) */ let sprites = entity.sprites let isJumping = entity.jumping || entity.falling let isRunning = (entity.right === true && !isJumping) || (entity.left === true && !isJumping) let isShooting = entity.shooting || false let sprite = !!sprites.run && isRunning ? sprites.run : !!sprites.jump && isJumping ? sprites.jump : !!sprites.shoot && isShooting ? sprites.shoot : sprites.idle const x = entity.bullet ? entity.x : entity.x + entity.dx * dt const y = entity.bullet ? entity.y - entity.height * 2 : entity.y + entity.dy * dt const flipped = entity.flipped const width = entity.bullet ? entity.width * 4 : entity.width const height = entity.bullet ? entity.height * 4 : entity.height let spriteTile = sprite.tiles[sprite.currentFrame] /* entity.pickups && console.log( 'log drawSprite currentFrame ', sprite.tiles[sprite.currentFrame] ) */ // make an image position using the // current row and colum spriteAtlas.sourceY = Math.floor(spriteTile / spriteAtlas.atlasCol) * spriteAtlas.tileSize spriteAtlas.sourceX = (spriteTile % spriteAtlas.atlasCol) * spriteAtlas.tileSize ctx.save() // * Flip Sprite ctx.scale(flipped ? -1 : 1, 1) let dx = flipped ? -x - width : x ctx.drawImage( spriteAtlas.tileAtlas, spriteAtlas.sourceX, spriteAtlas.sourceY, 16, // * source Höhe 16, // * source Breite dx, y, width, // * player Höhe height // * player Breite ) ctx.restore() updateFrames(frame, sprite) // entity.treasure && console.log('log drawSprite ', entity) } function updateFrames(frame, sprite) { /* entity.start.x === 48 && entity.start.y === 656 && console.log('log frame ', entity) */ if (frame % sprite.framebuffer === 0) { if (sprite.currentFrame + 1 < sprite.tiles.length) sprite.currentFrame++ else if (sprite.loop) sprite.currentFrame = 0 } } // * Render Player function renderPlayer(ctx, spriteAtlas, dt, frame) { if (player.vul === false) { ctx.globalAlpha = 0.25 + tweenTreasure(frame * 3, 60) } drawSprite(player, spriteAtlas, dt, frame) ctx.globalAlpha = 1 } function renderHud(ctx, spriteAtlas, dt, frame) { var n, max const hudScaling = scalingFactor / 2 const hitpoints = globalObject.hitpoints const killed = globalObject.killed const collected = globalObject.collected ctx.fillStyle = COLOR.GOLD for (n = 0, max = collected; n < max; n++) ctx.fillRect( t2p(1 + n) * hudScaling, t2p(1) * hudScaling, (TILE / 2) * hudScaling, (TILE / 2) * hudScaling ) ctx.fillStyle = COLOR.SLATE for (n = 0, max = killed; n < max; n++) ctx.fillRect( t2p(1 + n) * hudScaling, t2p(2) * hudScaling, (TILE / 2) * hudScaling, (TILE / 2) * hudScaling ) // ! provisorische Hitpoint-Anzeige ctx.fillStyle = 'red' if (hitpoints === 1) { ctx.globalAlpha = 0.25 + tweenTreasure(frame, 60) } for (n = 0, max = hitpoints; n < max; n++) ctx.fillRect( t2p(1 + n / 3) * hudScaling, t2p(3) * hudScaling, 4 * hudScaling, 8 * hudScaling ) // ! Der Atlas funktioniert so nicht weil die Tiles nicht quadratisch sind. // drawSprite(t, spriteAtlas, dt, frame) ctx.globalAlpha = 1 } function fadeScreen(frame, dt) { ctx.fillStyle = 'black' ctx.globalAlpha = 0 let duration = 100 pulse = frame % duration if (pulse < duration) { opacity = pulse / duration } else { opacity = 0 } ctx.fillRect(0, 0, width, height) ctx.globalAlpha = opacity //setInterval(show(), 800) // console.log('log opacity ', opacity) // console.log('log fade frame ', frame) // console.log('log fade pulse ', pulse) } // * Render Pause Function function renderPause() { if (paused) { ctx.save() ctx.scale(scalingFactor / 2, scalingFactor / 2) ctx.font = '12px C64 TrueType' ctx.fillStyle = 'white' ctx.textAlign = 'center' ctx.fillText('- pause -', scaledCanvas.width, scaledCanvas.height) ctx.restore() } } function renderCameraBox() { ctx.fillStyle = 'rgba(0, 0, 255, 0.2)' ctx.fillRect(cameraBox.x, cameraBox.y, cameraBox.width, cameraBox.height) } function renderMonsters(ctx, spriteAtlas, dt, frame) { ctx.fillStyle = COLOR.SLATE var n, max, monster for (n = 0, max = monsters.length; n < max; n++) { monster = monsters[n] if (monster.sprites === undefined && !monster.dead) ctx.fillRect( monster.x + monster.dx * dt, monster.y + monster.dy * dt, TILE, TILE ) if (monster.sprites !== undefined && !monster.dead) { drawSprite(monster, spriteAtlas, dt, frame) } } } function renderPickups(ctx, spriteAtlas, dt, frame) { //ctx.globalAlpha = 0.25 + tweenTreasure(frame, 60) var n, max, p for (n = 0, max = pickups.length; n < max; n++) { p = pickups[n] //console.log('log p.sprites.currentsprite ', p.sprites.currentFrame) if (p.sprites !== undefined && !p.collected) { drawSprite(p, spriteAtlas, dt, frame) } } //ctx.globalAlpha = 1 } function renderTreasure(ctx, spriteAtlas, dt, frame) { ctx.fillStyle = COLOR.GOLD ctx.globalAlpha = 0.25 + tweenTreasure(frame, 60) var n, max, t for (n = 0, max = treasure.length; n < max; n++) { t = treasure[n] //if (!t.collected) ctx.fillRect(t.x, t.y + TILE / 3, TILE, (TILE * 2) / 3) if (t.sprites !== undefined && !t.collected) { // console.log('log treasure entity ', t) drawSprite(t, spriteAtlas, dt, frame) } } ctx.globalAlpha = 1 } function tweenTreasure(frame, duration) { const half = duration / 2 pulse = frame % duration return pulse < half ? pulse / half : 1 - (pulse - half) / half } function renderBullets(ctx, spriteAtlas, dt, frame) { ctx.fillStyle = COLOR.GOLD var n, max, bullet for (n = 0, max = bullets.length; n < max; n++) { bullet = bullets[n] switch (bullet.ammoType) { case 'simpleGun': bullet.sprites = simpleBullet.sprites break case 'advancedGun': bullet.sprites = simpleBullet.sprites break } //console.log('log bullet ', bullet.sprites) //console.log('log bullet spriteAtlas ', spriteAtlas) if (bullet !== undefined) { if (bullet.sprites === undefined) { ctx.fillRect(bullet.x, bullet.y, ammoType.width, ammoType.height) } if (bullet.sprites !== undefined) { // console.log('log bullet entity ', bullet) drawSprite(bullet, spriteAtlas, dt, frame) } } } }