Merge remote-tracking branch 'origin/passingEvents'

This commit is contained in:
Marcin Kostrzewski 2020-04-06 00:51:14 +02:00
commit 6b279ce47f
28 changed files with 500 additions and 41 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 630 B

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -13,11 +13,12 @@
"hunger" : 20 "hunger" : 20
} }
}, },
{ {
"name" : "cranberry", "name" : "cranberry",
"position" : { "position" : {
"x": 7, "x": 7,
"y": 1 "y": 3
}, },
"isPickupable" : true, "isPickupable" : true,
"effect" : { "effect" : {
@ -26,5 +27,52 @@
"thirst" : 2, "thirst" : 2,
"hunger" : 10 "hunger" : 10
} }
},
{
"name" : "rabbit",
"position" : {
"x": 12,
"y": 16
},
"isPickupable" : true,
"effect" : {
"hp": 30,
"stamina": -5,
"thirst": -5,
"hunger": 40
}
},
{
"name" : "bush",
"position" : {
"x": 15,
"y": 9
},
"isPickupable" : false
},
{
"name" : "rock",
"position" : {
"x": 13,
"y": 2
},
"isPickupable" : false
},
{
"name" : "mushroom",
"position" : {
"x": 14,
"y": 3
},
"isPickupable": true,
"effect" : {
"hp": -50,
"stamina": 0,
"thirst": 0,
"hunger": 25
}
} }
] ]

View File

@ -8,6 +8,7 @@ class Entity(pygame.sprite.Sprite):
def __init__(self, texture, size, pos): def __init__(self, texture, size, pos):
super().__init__() super().__init__()
self.image, self.rect = self.getTexture(texture, size) self.image, self.rect = self.getTexture(texture, size)
self.image.set_colorkey((255, 255, 255))
self.rect.x = pos[0] self.rect.x = pos[0]
self.rect.y = pos[1] self.rect.y = pos[1]
self.id = self.getId() self.id = self.getId()

View File

@ -6,13 +6,21 @@ import pygame
class Player(Entity): class Player(Entity):
statistics: Statistics
def __init__(self, spawnpoint, size): def __init__(self, spawnpoint, size):
super().__init__("player.jpg", size, (spawnpoint[0] * size, spawnpoint[1] * size)) super().__init__("player.png", size, (spawnpoint[0] * size, spawnpoint[1] * size))
# Where the player is facing, 0 - north, 1 # Where the player is facing, 0 - north, 1
self.rotation = Rotations.NORTH self.rotation = Rotations.NORTH
self.statistics = Statistics(100, 100, 0, 100)
# How many steps has the player taken through its lifetime
self.movePoints = 0
# Move in a desired direction # Move in a desired direction
def move(self, rotation): def move(self, rotation):
self.movePoints += 1
# Player gets tired aswell!
self.applyFatigue()
if rotation.value == Rotations.NORTH.value: if rotation.value == Rotations.NORTH.value:
self.rect.y -= self.rect.w self.rect.y -= self.rect.w
elif rotation.value == Rotations.EAST.value: elif rotation.value == Rotations.EAST.value:
@ -22,14 +30,57 @@ class Player(Entity):
elif rotation.value == Rotations.WEST.value: elif rotation.value == Rotations.WEST.value:
self.rect.x -= self.rect.w self.rect.x -= self.rect.w
def applyFatigue(self):
# looses hunger every 10 steps taken
if self.movePoints % 10 == 0:
self.statistics.set_hunger(-10)
# gets more thirsty every 5 steps
if self.movePoints % 5 == 0:
self.statistics.set_thirst(10)
# gets tired every step
self.statistics.set_stamina(-2)
def getFacingCoord(self):
if self.rotation == Rotations.NORTH:
return self.rect.x, self.rect.y - (self.rect.h)
elif self.rotation == Rotations.SOUTH:
return self.rect.x, self.rect.y + (self.rect.h)
elif self.rotation == Rotations.EAST:
return self.rect.x + (self.rect.h), self.rect.y
elif self.rotation == Rotations.WEST:
return self.rect.x - (self.rect.h), self.rect.y
# Returns given statistic
def getStatistic(self, stat):
if stat.value == StatisticNames.HP:
return self.statistics.hp
elif stat.value == StatisticNames.HUNGER:
return self.statistics.hunger
elif stat.value == StatisticNames.THIRST:
return self.statistics.thirst
elif stat.value == StatisticNames.STAMINA:
return self.statistics.stamina
return None
def getStatistics(self):
return self.statistics
def rotate(self, rotation): def rotate(self, rotation):
# If the player is not facing given direction, it will not move the first time, it will only get rotated # If the player is not facing given direction, it will not move the first time, it will only get rotated
if self.rotation.value != rotation.value: if self.rotation.value != rotation.value:
self.image = pygame.transform.rotate(self.image, ((self.rotation.value - rotation.value) * 90)) self.image = pygame.transform.rotate(self.image, ((self.rotation.value - rotation.value) * 90))
self.rotation = rotation self.rotation = rotation
class Rotations(Enum): class Rotations(Enum):
NORTH = 0 NORTH = 0
EAST = 1 EAST = 1
SOUTH = 2 SOUTH = 2
WEST = 3 WEST = 3
class StatisticNames(Enum):
HP = 0
STAMINA = 1
HUNGER = 2
THIRST = 3

View File

@ -16,29 +16,29 @@ class Statistics:
self.hp = 100 self.hp = 100
def set_hunger(self, hunger_diff): def set_hunger(self, hunger_diff):
if 0 <= self.hp + hunger_diff <= 100: if 0 <= self.hunger + hunger_diff <= 100:
self.hp = self.hp + hunger_diff self.hunger = self.hunger + hunger_diff
else: else:
if self.hp + hunger_diff <= 0: if self.hunger + hunger_diff <= 0:
self.hp = 0 self.hunger = 0
else: else:
self.hp = 100 self.hunger = 100
def set_thirst(self, thirst_diff): def set_thirst(self, thirst_diff):
if 0 <= self.hp + thirst_diff <= 100: if 0 <= self.thirst + thirst_diff <= 100:
self.hp = self.hp + thirst_diff self.thirst = self.thirst + thirst_diff
else: else:
if self.hp + thirst_diff <= 0: if self.thirst + thirst_diff <= 0:
self.hp = 0 self.thirst = 0
else: else:
self.hp = 100 self.thirst = 100
def set_stamina(self, stamina_diff): def set_stamina(self, stamina_diff):
if 0 <= self.hp + stamina_diff <= 100: if 0 <= self.stamina + stamina_diff <= 100:
self.hp = self.hp + stamina_diff self.stamina = self.stamina + stamina_diff
else: else:
if self.hp + stamina_diff <= 0: if self.stamina + stamina_diff <= 0:
self.hp = 0 self.stamina = 0
else: else:
self.hp = 100 self.stamina = 100

View File

@ -1,5 +1,6 @@
import pygame import pygame
from src.entities.Pickupable import Pickupable
from src.entities.Player import Rotations from src.entities.Player import Rotations
# Player can move every given milliseconds # Player can move every given milliseconds
@ -21,19 +22,28 @@ class EventManager:
def handleEvents(self): def handleEvents(self):
pygame.event.pump() pygame.event.pump()
self.game.screen.ui.timerTextView.changeText(self.game.ingameTimer.getPrettyTime())
keys = pygame.key.get_pressed() keys = pygame.key.get_pressed()
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
self.game.running = False self.game.running = False
self.game.screen.ui.updateBasedOnPygameEvent(event)
self.keyTimeout += self.keyTimer.tick() self.keyTimeout += self.keyTimer.tick()
if self.keyTimeout >= TIMEOUT: if self.keyTimeout >= TIMEOUT:
self.handlePlayerControls(keys) self.handlePlayerControls(keys)
self.keyTimeout = 0 self.keyTimeout = 0
self.game.screen.ui.updateBasedOnPlayerStats(self.player.statistics)
def handlePlayerControls(self, keys): def handlePlayerControls(self, keys):
# Key names are temporary # Key names are temporary
# TODO: Load key bindings from JSON # TODO: Load key bindings from JSON
if keys[pygame.K_SPACE]:
object = self.game.map.getEntityOnCoord(self.player.getFacingCoord())
if type(object) is Pickupable:
object.on_pickup(self.player)
self.game.map.removeSpriteFromMap(object)
if keys[pygame.K_w]: if keys[pygame.K_w]:
self.player.rotate(Rotations.NORTH) self.player.rotate(Rotations.NORTH)
if not self.game.map.collision(self.player.rect.x, self.player.rect.y - self.player.rect.w): if not self.game.map.collision(self.player.rect.x, self.player.rect.y - self.player.rect.w):

View File

@ -6,7 +6,11 @@ from os import path
from game.EventManager import EventManager from game.EventManager import EventManager
from game.Screen import Screen from game.Screen import Screen
from game.Map import Map from game.Map import Map
from src.entities.Pickupable import Pickupable
from src.entities.Player import Player from src.entities.Player import Player
from src.entities.Statistics import Statistics
from src.game.Timer import Timer
class Game: class Game:
@ -37,6 +41,11 @@ class Game:
print("The screen cannot be in a vertical orientation. Exiting...") print("The screen cannot be in a vertical orientation. Exiting...")
exit(1) exit(1)
# Initialize timers
self.pgTimer = pygame.time.Clock()
self.ingameTimer = Timer()
self.ingameTimer.startClock()
self.screen = Screen(self, self.config["window"]) self.screen = Screen(self, self.config["window"])
print("OK") print("OK")
@ -50,6 +59,8 @@ class Game:
def mainLoop(self): def mainLoop(self):
while self.running: while self.running:
# Update ingame clock
self.ingameTimer.updateTime(self.pgTimer.tick())
self.eventManager.handleEvents() self.eventManager.handleEvents()
self.spritesList.draw(self.screen.pygameScreen) self.spritesList.draw(self.screen.pygameScreen)
pygame.display.flip() pygame.display.flip()

View File

@ -1,8 +1,8 @@
import json import json
import pygame import pygame
from game.TerrainTile import TerrainTile from src.game.TerrainTile import TerrainTile
from game.Screen import Locations from src.game.Screen import Locations
from src.entities.Entity import Entity from src.entities.Entity import Entity
from src.entities.Pickupable import Pickupable from src.entities.Pickupable import Pickupable
@ -42,7 +42,7 @@ class Map:
for entity in entityListJson: for entity in entityListJson:
try: try:
if entity["isPickupable"]: if entity["isPickupable"]:
actualEntities.append(Pickupable(entity["name"] + ".jpg", actualEntities.append(Pickupable(entity["name"] + ".png",
self.tileSize, self.tileSize,
(entity["position"]["x"] * self.tileSize, entity["position"]["y"] * self.tileSize), (entity["position"]["x"] * self.tileSize, entity["position"]["y"] * self.tileSize),
Statistics(entity["effect"]["hp"], Statistics(entity["effect"]["hp"],
@ -50,7 +50,7 @@ class Map:
entity["effect"]["thirst"], entity["effect"]["thirst"],
entity["effect"]["stamina"]))) entity["effect"]["stamina"])))
else: else:
actualEntities.append(Entity(entity["name"], actualEntities.append(Entity(entity["name"] + ".png",
self.tileSize, self.tileSize,
(entity["position"]["x"] * self.tileSize, entity["position"]["y"] * self.tileSize))) (entity["position"]["x"] * self.tileSize, entity["position"]["y"] * self.tileSize)))
except KeyError: except KeyError:
@ -67,7 +67,7 @@ class Map:
elif tile == '.': elif tile == '.':
self.screen.draw(TerrainTile(col, row, 'grass.png', self.tileSize), Locations.MAP, 0, 0) self.screen.draw(TerrainTile(col, row, 'grass.png', self.tileSize), Locations.MAP, 0, 0)
elif tile == 'x': elif tile == 'x':
object = TerrainTile(col, row, 'water.jpg', self.tileSize) object = TerrainTile(col, row, 'water.png', self.tileSize)
self.screen.draw(object, Locations.MAP, 0, 0) self.screen.draw(object, Locations.MAP, 0, 0)
self.collidables.add(object) self.collidables.add(object)
elif tile == 'w': elif tile == 'w':
@ -75,6 +75,13 @@ class Map:
self.screen.draw(object, Locations.MAP, 0, 0) self.screen.draw(object, Locations.MAP, 0, 0)
self.collidables.add(object) self.collidables.add(object)
def getEntityOnCoord(self, coord):
result = None
for entity in self.collidables:
if entity.rect.x == coord[0] and entity.rect.y == coord[1]:
result = entity
return result
def addEntity(self, entity): def addEntity(self, entity):
self.screen.draw(entity, Locations.MAP, 0, 0) self.screen.draw(entity, Locations.MAP, 0, 0)
self.collidables.add(entity) self.collidables.add(entity)

View File

@ -2,11 +2,19 @@ import math
from enum import Enum from enum import Enum
import pygame import pygame
from src.ui.Ui import Ui
# minimum UI width # minimum UI width
MARGIN = 300 MARGIN = 300
# screen locations enum
class Locations(Enum):
RIGHT_UI = 1
LEFT_UI = 2
MAP = 3
class Screen: class Screen:
def __init__(self, gameObject, windowConfig): def __init__(self, gameObject, windowConfig):
self.gameObject = gameObject self.gameObject = gameObject
@ -24,6 +32,8 @@ class Screen:
# draw a white rect to resemble map # draw a white rect to resemble map
pygame.draw.rect(self.pygameScreen, (255, 255, 255), [self.mapCoord, 0, self.mapSize, self.mapSize]) pygame.draw.rect(self.pygameScreen, (255, 255, 255), [self.mapCoord, 0, self.mapSize, self.mapSize])
self.__initUi__()
def calculateMapDimensions(self): def calculateMapDimensions(self):
result = 0 result = 0
expectedSize = self.winY expectedSize = self.winY
@ -49,9 +59,25 @@ class Screen:
def removeSprite(self, sprite): def removeSprite(self, sprite):
self.gameObject.spritesList.remove(sprite) self.gameObject.spritesList.remove(sprite)
def getUiWidth(self, location: Locations):
if location is Locations.RIGHT_UI:
return self.winX - (self.mapCoord + self.mapSize)
elif location is Locations.LEFT_UI:
return self.mapCoord
elif location is Locations.MAP:
return self.mapSize
# screen locations enum def __initUi__(self):
class Locations(Enum): self.ui = Ui(self.getUiWidth(Locations.RIGHT_UI), self.getUiWidth(Locations.LEFT_UI), self.winY,
RIGHT_UI = 1 self.gameObject.ingameTimer)
LEFT_UI = 2 self.draw(self.ui.timerTextView, Locations.LEFT_UI, 0, 0)
MAP = 3 self.draw(self.ui.isDayTextView, Locations.LEFT_UI, 0, 0)
self.draw(self.ui.console, Locations.LEFT_UI, 0, 0)
self.draw(self.ui.healthTextView, Locations.RIGHT_UI, 0, 0)
self.draw(self.ui.healthBar, Locations.RIGHT_UI, 0, 0)
self.draw(self.ui.hungerTextView, Locations.RIGHT_UI, 0, 0)
self.draw(self.ui.hungerBar, Locations.RIGHT_UI, 0, 0)
self.draw(self.ui.staminaTextView, Locations.RIGHT_UI, 0, 0)
self.draw(self.ui.staminaBar, Locations.RIGHT_UI, 0, 0)
self.draw(self.ui.thirstTextView, Locations.RIGHT_UI, 0, 0)
self.draw(self.ui.thirstBar, Locations.RIGHT_UI, 0, 0)

View File

@ -1,3 +1,101 @@
from enum import Enum
import pygame
from src.entities.Statistics import Statistics
from src.ui.UiBar import UiBar
from src.ui.UiConsole import UiConsole
from src.ui.UiText import UiText
class Ui(): class Ui():
def __init__(self): def __init__(self, rightUiWidth, leftUiWidth, screenHeight, timer, font=None):
self.elements = [] self.elements = pygame.sprite.Group()
self.leftUiWidth = leftUiWidth
self.rightUiWidth = rightUiWidth
self.screenHeight = screenHeight
self.barHeight = 25
if font is None:
font = pygame.font.Font(None, self.barHeight)
self.font = font
self.timer = timer
self.timerTextView = UiText(pygame.Rect(0, 0, leftUiWidth, self.barHeight), font=self.font,
text=timer.getPrettyTime(), textColor=Colors.WHITE.value,
backgroundColor=Colors.GRAY.value)
self.isDayTextView = UiText(
pygame.Rect(0, self.timerTextView.rect.y + self.barHeight, leftUiWidth, self.barHeight), text="Day",
font=self.font, backgroundColor=Colors.GRAY.value, textColor=Colors.WHITE.value)
self.healthTextView = UiText(pygame.Rect(0, 0, rightUiWidth, self.barHeight), text="Health points",
font=self.font, textColor=Colors.WHITE.value)
self.healthBar = UiBar(
pygame.Rect(0, self.healthTextView.rect.y + self.barHeight, rightUiWidth, self.barHeight))
self.hungerTextView = UiText(
pygame.Rect(0, self.healthBar.rect.y + self.barHeight, rightUiWidth, self.barHeight),
text="Hunger", font=self.font, textColor=Colors.WHITE.value)
self.hungerBar = UiBar(
pygame.Rect(0, self.hungerTextView.rect.y + self.barHeight, rightUiWidth, self.barHeight),
initialFilledPercent=0,
filledBarColor=Colors.YELLOW.value)
self.staminaTextView = UiText(
pygame.Rect(0, self.hungerBar.rect.y + self.barHeight, rightUiWidth, self.barHeight), text="Stamina",
font=self.font, textColor=Colors.WHITE.value)
self.staminaBar = UiBar(
pygame.Rect(0, self.staminaTextView.rect.y + self.barHeight, rightUiWidth, self.barHeight),
filledBarColor=Colors.GREEN.value)
self.thirstTextView = UiText(
pygame.Rect(0, self.staminaBar.rect.y + self.barHeight, rightUiWidth, self.barHeight), text="Thirst",
font=self.font, textColor=Colors.WHITE.value)
self.thirstBar = UiBar(
pygame.Rect(0, self.thirstTextView.rect.y + self.barHeight, rightUiWidth, self.barHeight),
initialFilledPercent=0,
filledBarColor=Colors.BLUE.value)
self.console = UiConsole(pygame.Rect(0, self.timerTextView.rect.h + self.isDayTextView.rect.h, leftUiWidth,
screenHeight - self.timerTextView.rect.h - self.isDayTextView.rect.h),
font=self.font)
def updateBasedOnPlayerStats(self, statistics: Statistics):
consoleLines = []
if self.healthBar.value != statistics.hp:
self.healthBar.updateFill(statistics.hp)
consoleLines.append("Health: " + str(statistics.hp))
if self.hungerBar.value != statistics.hunger:
self.hungerBar.updateFill(statistics.hunger)
consoleLines.append("Hunger: " + str(statistics.hunger))
if self.staminaBar.value != statistics.stamina:
self.staminaBar.updateFill(statistics.stamina)
consoleLines.append("Stamina: " + str(statistics.stamina))
if self.thirstBar.value != statistics.thirst:
self.thirstBar.updateFill(statistics.thirst)
consoleLines.append("Stamina: " + str(statistics.thirst))
if len(consoleLines) > 0:
self.console.addLinesToConsoleAndScrollToDisplayThem(consoleLines)
def updateBasedOnPygameEvent(self, event: pygame.event):
if event.type == pygame.MOUSEBUTTONDOWN:
console = self.console
if event.button == 4:
console.writeConsoleLines(console.topWrittenLineInd + 1)
elif event.button == 5:
console.writeConsoleLines(console.topWrittenLineInd - 1)
class Colors(Enum):
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
GRAY = (125, 125, 125)

View File

@ -1,5 +1,32 @@
import src.ui.UiElement as UiElement import pygame
from src.ui.UiElement import UiElement
class UiBar(UiElement): class UiBar(UiElement):
pass def __init__(self, rect: pygame.Rect, initialFilledPercent=100, filledBarColor=(255, 0, 0), emptyBarColor=(0, 0, 0),
outlineColor=(75, 75, 75), outlineThickness=10):
super().__init__(rect)
self.filledPercent = initialFilledPercent / 100
self.emptyBarColor = emptyBarColor
self.barColor = filledBarColor
self.outlineColor = outlineColor
self.outlineThickness = outlineThickness
self.filledBarColor = filledBarColor
self.value = initialFilledPercent
self.__genBar__()
def __genBar__(self):
self.image = pygame.Surface((self.rect.width, self.rect.height))
filledPartRect = pygame.rect.Rect(self.outlineThickness / 2, self.outlineThickness / 2,
(self.rect.width - self.outlineThickness) * self.filledPercent,
self.rect.height - self.outlineThickness)
self.image.fill(self.filledBarColor, filledPartRect)
pygame.draw.rect(self.image, self.outlineColor, pygame.rect.Rect(0, 0, self.rect.width, self.rect.height),
self.outlineThickness)
def updateFill(self, filledPercent):
self.filledPercent = filledPercent / 100
self.value = filledPercent
self.__genBar__()

View File

@ -1,5 +1,67 @@
import src.ui.UiElement as UiElement from enum import Enum
import pygame
from src.ui.UiElement import UiElement
class UiButton(UiElement): class UiButton(UiElement):
pass
def __init__(self, rect: pygame.Rect, notClickedBtnColor=(125, 125, 125), clickedBtnColor=(255, 255, 255),
text="Click", textColor=(0, 0, 0), font=None, functionsToInvokeWhenClicked=[]):
"""
:type functionsToInvokeWhenClicked : list of tuple(function, args*), args are function arguments
"""
super().__init__(rect)
if font is None:
font = pygame.font.Font(None, 25)
self.font = font
self.textColor = textColor
self.clickedBtnColor = clickedBtnColor
self.notClickedBtnColor = notClickedBtnColor
self.text = text
self.__initBtnImages__()
self.beingClicked = False
self.image = self._images[0]
self.functionsToInvokeWhenClicked = []
self.functionsToInvokeWhenClicked.extend(functionsToInvokeWhenClicked)
def eventHandler(self, event):
# change selected color if rectangle clicked
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if self.rect.collidepoint(event.pos): # is mouse over button
self.image = self._images[ButtonImages.CLICKING_IMAGE.value]
self.beingClicked = True
for func, *args in self.functionsToInvokeWhenClicked:
func(*args)
elif event.type == pygame.MOUSEBUTTONUP and self.beingClicked:
if event.button == 1:
self.beingClicked = False
self.image = self._images[ButtonImages.DEFAULT_IMAGE.value]
def __initBtnImages__(self):
self._images = [
pygame.Surface((self.rect.width, self.rect.height)),
pygame.Surface((self.rect.width, self.rect.height)),
]
self._images[ButtonImages.DEFAULT_IMAGE.value].fill(self.notClickedBtnColor)
self._images[ButtonImages.CLICKING_IMAGE.value].fill(self.clickedBtnColor)
self.textSurface = self.font.render(self.text, False, (0, 0, 0))
self.textSurfaceDest = (self.rect.centerx - (self.textSurface.get_width() / 2),
self.rect.centery - (self.textSurface.get_height() / 2))
self._images[0].blit(self.textSurface, self.textSurfaceDest)
self._images[1].blit(self.textSurface, self.textSurfaceDest)
def addFuncToInvoke(self, tupleOfFuncAndArgs):
"""
:type tupleOfFuncAndArgs: tuple(function, *args)
"""
self.functionsToInvokeWhenClicked.append(tupleOfFuncAndArgs)
class ButtonImages(Enum):
DEFAULT_IMAGE = 0
CLICKING_IMAGE = 1

79
src/ui/UiConsole.py Normal file
View File

@ -0,0 +1,79 @@
import pygame
from src.ui.UiElement import UiElement
class UiConsole(UiElement):
def __init__(self, rect: pygame.Rect, bgColor=(125, 125, 125), textColor=(255, 255, 255), font=None):
super().__init__(rect)
self.textColor = textColor
if font is None:
font = pygame.font.Font(None, 25)
self.font = font
self.bgColor = bgColor
self.image = pygame.Surface((rect.width, rect.height))
self.image.fill(bgColor)
self.consoleWidth = self.image.get_width()
self.linesImagesCount = 0
self.consoleLines = []
self.linesCount = 0
self.topWrittenLineInd = 0
self.linesImages = []
self.lineHeight = font.render("sampleText", False, textColor).get_height()
self.maxLines = int(self.image.get_height() / self.lineHeight)
self.addLinesToConsole(["Hello from console!"])
self.writeConsoleLines()
def writeConsoleLines(self, startingLineInd=0):
self.image.fill(self.bgColor)
if startingLineInd < 0:
startingLineInd = 0
elif startingLineInd >= self.linesImagesCount:
startingLineInd = self.linesImagesCount - 1
self.topWrittenLineInd = startingLineInd
writtenLines = 0
for i in range(startingLineInd, min(self.maxLines + startingLineInd, self.linesImagesCount)):
self.image.blit(self.linesImages[i], (0, writtenLines * self.lineHeight))
writtenLines += 1
def addLinesToConsole(self, linesToAdd):
for line in linesToAdd:
self.consoleLines.append(line)
self.linesCount += 1
row = pygame.Surface((self.consoleWidth, self.lineHeight))
row.fill(self.bgColor)
howMuchRowIsFilled = 0
words = line.split(' ')
for word in words:
wordImage = self.font.render(' ' + word, False, self.textColor)
if howMuchRowIsFilled + wordImage.get_width() <= self.consoleWidth:
row.blit(wordImage, (howMuchRowIsFilled, 0))
howMuchRowIsFilled += wordImage.get_width()
else:
self.linesImages.append(row)
self.linesImagesCount += 1
row = pygame.Surface((self.consoleWidth, self.lineHeight))
row.fill(self.bgColor)
howMuchRowIsFilled = 0
row.blit(wordImage, (howMuchRowIsFilled, 0))
howMuchRowIsFilled += wordImage.get_width()
self.linesImages.append(row)
self.linesImagesCount += 1
def addLinesToConsoleAndScrollToDisplayThem(self, linesToAdd):
self.addLinesToConsole(linesToAdd)
ind = 0
if self.linesImagesCount > self.maxLines:
ind = self.linesImagesCount - self.maxLines
self.writeConsoleLines(ind)

View File

@ -1,2 +1,7 @@
class UiElement: import pygame
pass
class UiElement(pygame.sprite.Sprite):
def __init__(self, rect):
super().__init__()
self.rect = rect

View File

@ -1,5 +1,10 @@
import src.ui.UiElement as UiElement from src.ui.UiElement import UiElement
import pygame
class UiImage(UiElement): class UiImage(UiElement):
pass def __init__(self, rect: pygame.Rect, image: pygame.Surface):
super().__init__(rect)
self.image = pygame.transform.scale(image, (rect.width, rect.height))

View File

@ -1,5 +1,34 @@
import src.ui.UiElement as UiElement from typing import Tuple
import pygame
from src.ui.UiElement import UiElement
class UiText(UiElement): class UiText(UiElement):
pass def __init__(self, rect: pygame.Rect, text: str, font: pygame.font.Font = None,
textColor=(0, 0, 0), antialias: bool = False,
backgroundColor=None):
super().__init__(rect)
self.backgroundColor = backgroundColor
self.antialias = antialias
self.textColor = textColor
self.text = text
if font is None:
font = pygame.font.Font(None, 12)
self.font = font
self.image = pygame.Surface((rect.w, rect.h))
if backgroundColor is not None:
self.image.fill(backgroundColor)
wordImage = self.font.render(text, antialias, textColor)
self.image.blit(wordImage, (0, 0))
def changeText(self, newText):
self.text = newText
if self.backgroundColor is not None:
self.image.fill(self.backgroundColor)
wordImage = self.font.render(self.text, self.antialias, self.textColor)
self.image.blit(wordImage, (0, 0))