-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
expand ECS part +versioning a new experiment(adapt riks ideas)
- Loading branch information
Showing
18 changed files
with
1,610 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import pygame | ||
from core_component import Component | ||
# from ..core.colours import * | ||
|
||
|
||
class CameraComponent(Component): | ||
|
||
def __init__(self, | ||
|
||
# required parameters | ||
x, y, | ||
w, h, | ||
|
||
# optional parameters | ||
bgColour=None, | ||
sceneX = 0, sceneY = 0, | ||
entityToTrack = None, | ||
zoomLevel = 1, | ||
clampToMap = True | ||
|
||
): | ||
|
||
self.key = 'camera' | ||
|
||
self.rect = pygame.Rect(x, y, w, h) | ||
self.bgColour = bgColour | ||
|
||
self.sceneX = sceneX | ||
self.sceneY = sceneY | ||
self.entityToTrack = entityToTrack | ||
self.zoomLevel = zoomLevel | ||
|
||
self.zoomPerFrame = 0 | ||
self.targetZoom = self.zoomLevel | ||
|
||
self.targetX = 0 | ||
self.targetY = 0 | ||
self.movementPerFrameX = 0 | ||
self.movementPerFrameY = 0 | ||
|
||
self.clampToWorld = clampToMap | ||
|
||
self._x = 0 | ||
self._y = 0 | ||
self._z = 0 | ||
|
||
def setZoom(self, level, duration=1): | ||
if duration < 1: | ||
return | ||
self.targetZoom = level | ||
self.zoomPerFrame = (self.targetZoom - self.zoomLevel) / duration | ||
|
||
def setPosition(self, x, y, duration=1): | ||
if duration < 1: | ||
return | ||
self.entityToTrack = None | ||
self.targetX = x | ||
self.targetY = y | ||
self.movementPerFrameX = (self.targetX - self.sceneX) / duration | ||
self.movementPerFrameY = (self.targetY - self.sceneY) / duration | ||
|
||
# sets the zoom level and position | ||
# so that the entire map is visible in the camera | ||
def setFullScreen(self, map): | ||
|
||
# set the camera to the center of the world | ||
self.sceneX = map.w_real / 2 | ||
self.sceneY = map.h_real / 2 | ||
# set the zoom level | ||
if (self.rect.width / map.w_real) < (self.rect.height / map.h_real): | ||
z = self.rect.width / map.w_real | ||
else: | ||
z = self.rect.height / map.h_real | ||
self.zoomLevel = z | ||
|
||
def _updateWorldPosition(self, x, y, scene): | ||
|
||
newX = x | ||
newY = y | ||
|
||
if scene is not None and scene.map is not None and self.clampToWorld: | ||
|
||
# calculate x value | ||
|
||
# if scene narrower than camera: | ||
if (self.rect.w) > (scene.map.w_real*self.zoomLevel): | ||
newX = int(scene.map.w_real / 2) | ||
else: | ||
newX = max(newX, (self.rect.w/self.zoomLevel)/2) | ||
newX = min(newX, ( ((scene.map.w_real) - (self.rect.w/2/self.zoomLevel)) ) ) | ||
|
||
# calculate y value | ||
|
||
# if scene narrower than camera: | ||
if self.rect.h > (scene.map.h_real*self.zoomLevel): | ||
newY = int(scene.map.h_real / 2) | ||
else: | ||
newY = max(newY, (self.rect.h/self.zoomLevel/2)) | ||
newY = min(newY, ( ((scene.map.h_real) - (self.rect.h/2/self.zoomLevel)) ) ) | ||
|
||
self.sceneX = newX | ||
self.sceneY = newY | ||
|
||
def trackEntity(self, entity): | ||
self.entityToTrack = entity | ||
|
||
def goToEntity(self, entity): | ||
self.entityToTrack = None | ||
pos = entity.getComponent('position') | ||
self.sceneX = pos.rect.x + (pos.rect.w / 2) | ||
self.sceneY = pos.rect.y + (pos.rect.h / 2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,279 @@ | ||
#from .gamma import soundManager, inputManager | ||
#from .core.component import Component | ||
#from .core.colours import * | ||
#from ..renderables.text import Text | ||
from core_component import Component | ||
import pygame | ||
|
||
# used to be the import.set of file embedding cls:Text | ||
# from ..gamma import resourceManager | ||
# from ..core.renderable import Renderable | ||
# from ..core.colours import WHITE | ||
# from ..utils.utils_draw import blit_alpha | ||
|
||
|
||
class Text: | ||
|
||
def __init__(self, | ||
|
||
# required parameters | ||
text, x, y, | ||
|
||
# optional parameters | ||
hAlign='left', vAlign='top', | ||
colour="white", | ||
alpha=255, | ||
font=pygame.font.Font(None, 15), #resourceManager.getFont('munro24'), | ||
underline=False, | ||
z=1, | ||
xParallax=False, yParallax=False | ||
|
||
): | ||
super().__init__(x, y, z, hAlign, vAlign, colour, alpha, xParallax, yParallax) | ||
|
||
# set additional text object parameters | ||
self._text = str(text) | ||
self.font = font | ||
self.underline = underline | ||
self._createSurface() | ||
|
||
def _createSurface(self): | ||
self.font.set_underline(self.underline) | ||
self.textSurface = self.font.render(self._text, True, self.colour) | ||
self.rect = self.textSurface.get_rect() | ||
self._align() | ||
|
||
def draw(self, surface, xOff=0, yOff=0, scale=1): | ||
x = self.rect.x * scale + xOff | ||
y = self.rect.y * scale + yOff | ||
blit_alpha(surface, self.textSurface, (x, y), self._alpha) | ||
|
||
# text property | ||
|
||
@property | ||
def text(self): | ||
return self._text | ||
|
||
@text.setter | ||
def text(self, value): | ||
self._text = str(value) | ||
self._createSurface() | ||
|
||
|
||
class TextComponent(Component): | ||
|
||
def __init__(self, | ||
|
||
# required parameters | ||
|
||
text, | ||
|
||
# optional parameters | ||
|
||
# position (only if overhead = False) | ||
x = 20, y = 20, | ||
# colour | ||
textColour = "white", | ||
# minimum text character width | ||
textWidth = 20, | ||
# spacing between rows of text | ||
spacing = 15, | ||
# display above the entity, or at bottom of scene | ||
overhead = True, | ||
# how long to display the text | ||
# options are 'always', 'timed', or 'press' | ||
lifetime = 'always', | ||
# how the text appears | ||
# options are 'appear', 'fade' or 'tick' | ||
type = 'appear', | ||
# display a new character every [x] frames | ||
tick_delay = 5, | ||
# sound to play when advancing tick animation | ||
tick_sound = None, | ||
# display time before fading out (if lifetime='fade') | ||
final_display_time = 300, | ||
# inputs that can control the text (if lifetime='press') | ||
input_list = None | ||
|
||
): | ||
|
||
self.key = 'text' | ||
|
||
# store component attributes | ||
|
||
self.text = text | ||
self.x = x | ||
self.y = y | ||
self.textColour = textColour | ||
self.textWidth = textWidth | ||
self.spacing = spacing | ||
self.overhead = overhead | ||
self.lifetime = lifetime | ||
self.tick_delay = tick_delay | ||
self.tick_sound = tick_sound | ||
self.final_display_time = final_display_time | ||
self.input_list = input_list | ||
self._setType(type) | ||
|
||
# attributes to store current state | ||
|
||
# timer used to tick the text forward | ||
self.delayTimer = self.tick_delay | ||
# stores the text, divided into rows | ||
self.textList = [] | ||
# lets the TextSystem know when to delete the component | ||
self.destroy = False | ||
# keeps track of fade direction (in or out) | ||
self.enterOrExit = 'enter' | ||
|
||
# split the text into multiple rows, | ||
# using self.width as a minimum characher width | ||
|
||
row = '' | ||
for char in self.text: | ||
row = row + char | ||
if len(row) >= self.textWidth and char == ' ': | ||
self.textList.append(row[:-1]) | ||
row = '' | ||
if len(row) > 0: | ||
self.textList.append(row) | ||
|
||
# add hint to press button | ||
if self.lifetime == 'press': | ||
self.textList[-1] += ' >>' | ||
|
||
def _setType(self, type): | ||
|
||
# types are 'appear', 'tick' or 'fade' | ||
self.type = type | ||
|
||
if self.type == 'appear': | ||
self.finished = True | ||
self.index = self.width | ||
self.row = len(self.textList) | ||
self.fadeAmount = 255 | ||
|
||
if self.type == 'tick': | ||
self.finished = False | ||
self.index = 0 | ||
self.row = 0 | ||
self.fadeAmount = 255 | ||
|
||
if self.type == 'fade': | ||
self.fadeAmount = 0 | ||
self.finished = False | ||
self.index = self.width | ||
self.row = len(self.textList) | ||
|
||
def update(self): | ||
|
||
# no need to update if just showing all text | ||
if self.type == 'appear': | ||
pass | ||
|
||
# if text is appearing ticked | ||
if self.type == 'tick' and self.enterOrExit == 'enter': | ||
if not self.finished: | ||
# wait for tick timer | ||
self.delayTimer -= 1 | ||
if self.delayTimer <= 0: | ||
self.delayTimer = self.tick_delay | ||
# increment text | ||
self.index += 1 | ||
if self.tick_sound: | ||
soundManager.playSound(self.tick_sound, soundManager.soundVolume / 2) | ||
# move to tick the next row of text | ||
if self.index >= len(self.textList[self.row]): | ||
self.index = 0 | ||
self.row += 1 | ||
# finish once at the end of the last row | ||
if self.row >= len(self.textList): | ||
self.finished = True | ||
|
||
# if fading in | ||
if self.type == 'fade' and self.enterOrExit == 'enter': | ||
self.fadeAmount = min(self.fadeAmount+4, 255) | ||
if self.fadeAmount == 255: | ||
self.finished = True | ||
|
||
# start exising once enter animations complete | ||
if self.finished and self.enterOrExit == 'enter': | ||
|
||
if self.lifetime == 'always': | ||
pass | ||
|
||
if self.lifetime == 'timed': | ||
self.final_display_time -= 1 | ||
if self.final_display_time <= 0: | ||
self.enterOrExit = 'exit' | ||
|
||
# press to advance, regardless of progress | ||
if self.lifetime == 'press': | ||
if self.input_list is not None: | ||
for input in self.input_list: | ||
if inputManager.isPressed(input): | ||
self.enterOrExit = 'exit' | ||
|
||
# fade out the required amount (may be none) | ||
# and then destroy component | ||
if self.enterOrExit == 'exit': | ||
|
||
self.fadeAmount = max(self.fadeAmount - 5, 0) | ||
if self.fadeAmount == 0: | ||
self.destroy = True | ||
|
||
def draw(self, scene, x, y): | ||
|
||
rows = self.spacing * len(self.textList) | ||
|
||
for i,l in enumerate(self.textList): | ||
|
||
# don't draw all of the current row if ticking | ||
if i == self.row: | ||
|
||
if self.overhead: | ||
|
||
# draw above the entity | ||
scene.renderer.add(Text( | ||
l[0:self.index], | ||
x, | ||
y-10-rows+(i*self.spacing), | ||
colour=self.textColour, | ||
alpha=self.fadeAmount | ||
), scene=False) | ||
|
||
else: | ||
|
||
# draw at required x/y position | ||
scene.renderer.add(Text( | ||
l[0:self.index], | ||
self.x, | ||
self.y+(i*self.spacing*2), | ||
colour=self.textColour, | ||
alpha=self.fadeAmount | ||
)) | ||
|
||
# draw previous rows | ||
elif i < self.row: | ||
|
||
if self.overhead: | ||
|
||
# draw above the entity | ||
scene.renderer.add(Text( | ||
l, | ||
x, | ||
y-10-rows+(i*self.spacing), | ||
colour=self.textColour, | ||
alpha=self.fadeAmount | ||
), scene=False) | ||
|
||
else: | ||
|
||
# draw at required x/y position | ||
scene.renderer.add(Text( | ||
l, | ||
self.x, | ||
self.y+(i*self.spacing*2), | ||
colour=self.textColour, | ||
alpha=self.fadeAmount | ||
)) |
Oops, something went wrong.