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