feat(render): renderer scaffolding and theme
This commit is contained in:
1 parent
dccc3a8b4e
commit
2016a02e89
3 files changed
+167
No files matched your search
@@ -0,0 +1,4 @@
|
|||||||
|
from .renderer import Renderer
|
||||||
|
from .art import buildSprites
|
||||||
|
|
||||||
|
__all__ = ["Renderer", "buildSprites"]
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
import pygame
|
||||||
|
|
||||||
|
from ..constants import tileSize
|
||||||
|
from ..sim.tiles import AIR
|
||||||
|
from .theme import (
|
||||||
|
bufferWidth,
|
||||||
|
bufferHeight,
|
||||||
|
renderScale,
|
||||||
|
skyTop,
|
||||||
|
skyBottom,
|
||||||
|
hillFar,
|
||||||
|
hillNear,
|
||||||
|
cloudColor,
|
||||||
|
)
|
||||||
|
from .art import buildSprites
|
||||||
|
from .hud import Hud
|
||||||
|
|
||||||
|
|
||||||
|
class Renderer:
|
||||||
|
def __init__(self, sprites=None):
|
||||||
|
self.sprites = sprites if sprites is not None else buildSprites()
|
||||||
|
self.hud = Hud()
|
||||||
|
self.buffer = pygame.Surface((bufferWidth, bufferHeight))
|
||||||
|
self.sky = self.buildSky()
|
||||||
|
|
||||||
|
def buildSky(self):
|
||||||
|
surf = pygame.Surface((bufferWidth, bufferHeight))
|
||||||
|
for y in range(bufferHeight):
|
||||||
|
blend = y / bufferHeight
|
||||||
|
color = (
|
||||||
|
int(skyTop[0] + (skyBottom[0] - skyTop[0]) * blend),
|
||||||
|
int(skyTop[1] + (skyBottom[1] - skyTop[1]) * blend),
|
||||||
|
int(skyTop[2] + (skyBottom[2] - skyTop[2]) * blend),
|
||||||
|
)
|
||||||
|
pygame.draw.line(surf, color, (0, y), (bufferWidth, y))
|
||||||
|
return surf
|
||||||
|
|
||||||
|
def drawParallax(self, offsetX):
|
||||||
|
self.buffer.blit(self.sky, (0, 0))
|
||||||
|
for hillX in (40, 220, 430, 620, 820):
|
||||||
|
screenX = hillX - offsetX // 2 % 900
|
||||||
|
pygame.draw.ellipse(self.buffer, hillFar, (screenX, bufferHeight - 52, 140, 80))
|
||||||
|
pygame.draw.ellipse(self.buffer, hillNear, (screenX + 22, bufferHeight - 44, 96, 64))
|
||||||
|
for cloudX in (90, 260, 470, 640, 820):
|
||||||
|
screenX = cloudX - offsetX // 3 % 900
|
||||||
|
pygame.draw.ellipse(self.buffer, cloudColor, (screenX, 26, 46, 20))
|
||||||
|
pygame.draw.ellipse(self.buffer, cloudColor, (screenX + 18, 18, 40, 24))
|
||||||
|
|
||||||
|
def drawTiles(self, world, offsetX, offsetY):
|
||||||
|
level = world.level
|
||||||
|
firstCol = max(0, offsetX // tileSize)
|
||||||
|
lastCol = min(level.cols, (offsetX + bufferWidth) // tileSize + 1)
|
||||||
|
firstRow = max(0, offsetY // tileSize)
|
||||||
|
lastRow = min(level.rows, (offsetY + bufferHeight) // tileSize + 1)
|
||||||
|
for row in range(firstRow, lastRow):
|
||||||
|
for col in range(firstCol, lastCol):
|
||||||
|
name = level.collision[row][col]
|
||||||
|
if name == AIR:
|
||||||
|
continue
|
||||||
|
sprite = self.sprites.get(name)
|
||||||
|
if sprite is None:
|
||||||
|
continue
|
||||||
|
self.buffer.blit(sprite, (col * tileSize - offsetX, row * tileSize - offsetY))
|
||||||
|
|
||||||
|
def drawItems(self, world, offsetX, offsetY):
|
||||||
|
for item in world.items:
|
||||||
|
if item.collected:
|
||||||
|
continue
|
||||||
|
sprite = self.sprites.get(item.kind)
|
||||||
|
if sprite is None:
|
||||||
|
continue
|
||||||
|
bob = -2 if (item.bob and int(item.bobPhase * 2) % 2 == 0) else 0
|
||||||
|
self.buffer.blit(sprite, (int(item.x) - offsetX, int(item.y) - offsetY + bob))
|
||||||
|
|
||||||
|
def drawEnemies(self, world, offsetX, offsetY):
|
||||||
|
for enemy in world.enemies:
|
||||||
|
if not enemy.alive:
|
||||||
|
continue
|
||||||
|
sprite = self.sprites.get(enemy.kind, self.sprites["goomba"])
|
||||||
|
if enemy.facing > 0:
|
||||||
|
sprite = pygame.transform.flip(sprite, True, False)
|
||||||
|
self.buffer.blit(sprite, (int(enemy.x) - offsetX, int(enemy.y) - offsetY))
|
||||||
|
|
||||||
|
def drawProjectiles(self, world, offsetX, offsetY):
|
||||||
|
for projectile in world.projectiles:
|
||||||
|
if not projectile.alive:
|
||||||
|
continue
|
||||||
|
x = int(projectile.centerX) - offsetX
|
||||||
|
y = int(projectile.centerY) - offsetY
|
||||||
|
pygame.draw.circle(self.buffer, (255, 160, 60), (x, y), 3)
|
||||||
|
pygame.draw.circle(self.buffer, (255, 240, 180), (x, y), 1)
|
||||||
|
|
||||||
|
def drawParticles(self, world, offsetX, offsetY):
|
||||||
|
for particle in world.particles.particles:
|
||||||
|
x = int(particle.x) - offsetX
|
||||||
|
y = int(particle.y) - offsetY
|
||||||
|
self.buffer.fill(particle.color, (x, y, particle.size, particle.size))
|
||||||
|
|
||||||
|
def drawPlayer(self, world, offsetX, offsetY):
|
||||||
|
player = world.player
|
||||||
|
if not player.alive:
|
||||||
|
return
|
||||||
|
if player.iframes > 0 and player.iframes % 6 < 3:
|
||||||
|
return
|
||||||
|
sprite = self.sprites["player"]
|
||||||
|
if player.facing < 0:
|
||||||
|
sprite = pygame.transform.flip(sprite, True, False)
|
||||||
|
self.buffer.blit(sprite, (int(player.x) - 2 - offsetX, int(player.y) - offsetY))
|
||||||
|
|
||||||
|
def renderWorld(self, world):
|
||||||
|
offsetX, offsetY = world.camera.offset()
|
||||||
|
self.drawParallax(offsetX)
|
||||||
|
self.drawTiles(world, offsetX, offsetY)
|
||||||
|
self.drawItems(world, offsetX, offsetY)
|
||||||
|
self.drawProjectiles(world, offsetX, offsetY)
|
||||||
|
self.drawEnemies(world, offsetX, offsetY)
|
||||||
|
self.drawParticles(world, offsetX, offsetY)
|
||||||
|
self.drawPlayer(world, offsetX, offsetY)
|
||||||
|
return self.buffer
|
||||||
|
|
||||||
|
def present(self, world, mode=None):
|
||||||
|
self.renderWorld(world)
|
||||||
|
scaled = pygame.transform.scale(
|
||||||
|
self.buffer, (bufferWidth * renderScale, bufferHeight * renderScale)
|
||||||
|
)
|
||||||
|
self.hud.draw(scaled, world)
|
||||||
|
if mode in ("menu", "paused", "gameover", "complete", "victory"):
|
||||||
|
self.hud.drawOverlay(scaled, mode)
|
||||||
|
return scaled
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
from ..constants import viewWidth, viewHeight
|
||||||
|
|
||||||
|
bufferWidth = viewWidth
|
||||||
|
bufferHeight = viewHeight
|
||||||
|
renderScale = 3
|
||||||
|
|
||||||
|
skyTop = (58, 122, 210)
|
||||||
|
skyBottom = (150, 205, 255)
|
||||||
|
caveTop = (24, 20, 40)
|
||||||
|
caveBottom = (48, 40, 74)
|
||||||
|
|
||||||
|
hillFar = (0, 150, 96)
|
||||||
|
hillNear = (0, 190, 120)
|
||||||
|
cloudColor = (255, 255, 255)
|
||||||
|
|
||||||
|
hudTextColor = (255, 255, 255)
|
||||||
|
hudShadowColor = (0, 0, 0)
|
||||||
|
heartFull = (224, 48, 64)
|
||||||
|
heartEmpty = (70, 30, 34)
|
||||||
|
|
||||||
|
tileFallback = {
|
||||||
|
"ground": (198, 100, 29),
|
||||||
|
"brick": (181, 94, 41),
|
||||||
|
"stone": (110, 110, 128),
|
||||||
|
"dirt": (120, 72, 40),
|
||||||
|
"platform": (217, 164, 65),
|
||||||
|
"woodOneWay": (168, 120, 68),
|
||||||
|
"spike": (200, 200, 210),
|
||||||
|
"lava": (224, 90, 30),
|
||||||
|
"ladder": (150, 100, 50),
|
||||||
|
"ladderTop": (170, 120, 60),
|
||||||
|
"slopeRight": (150, 74, 18),
|
||||||
|
"slopeLeft": (150, 74, 18),
|
||||||
|
}
|
||||||
Reference in new issue
Block a user