396 lines
10 KiB
JavaScript
396 lines
10 KiB
JavaScript
//-------------------------------------------------------------------------
|
|
// 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)
|
|
renderVehicless(ctx, enemyAtlas, 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 renderVehicless(ctx, spriteAtlas, dt, frame) {
|
|
ctx.fillStyle = COLOR.BRICK
|
|
var n, max, vehicle
|
|
for (n = 0, max = vehicles.length; n < max; n++) {
|
|
vehicle = vehicles[n]
|
|
|
|
if (vehicle.sprites === undefined && !vehicle.dead)
|
|
ctx.fillRect(
|
|
vehicle.x + vehicle.dx * dt,
|
|
vehicle.y + vehicle.dy * dt,
|
|
32,
|
|
32
|
|
)
|
|
if (vehicle.sprites !== undefined && !vehicle.dead) {
|
|
//drawSprite(vehicle, spriteAtlas, dt, frame)
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
}
|