diff --git a/.gitignore b/.gitignore index 78b759b..215a7f5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /.idea/ __pycache__ +/venv/ diff --git a/data/images/entities/bush.png b/data/images/entities/bush.png new file mode 100644 index 0000000..a59627d Binary files /dev/null and b/data/images/entities/bush.png differ diff --git a/data/images/entities/treasure.png b/data/images/entities/treasure.png new file mode 100644 index 0000000..a795552 Binary files /dev/null and b/data/images/entities/treasure.png differ diff --git a/src/entities/Collidable.py b/src/entities/Collidable.py index 72a7c36..9ecf2eb 100644 --- a/src/entities/Collidable.py +++ b/src/entities/Collidable.py @@ -14,7 +14,7 @@ class Collidable(Entity): return False -col = Collidable(1, 1, 1) +#col = Collidable(1, 1, 1) """ diff --git a/src/entities/Player.py b/src/entities/Player.py index 3f33f5b..c47fc35 100644 --- a/src/entities/Player.py +++ b/src/entities/Player.py @@ -13,25 +13,20 @@ class Player(Entity): # Move in a desired direction def move(self, rotation): - # 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: - self.rotate(rotation) - # Otherwise, move one tile to a given direction - else: - # TODO: Collision checks - if rotation.value == Rotations.NORTH.value: - self.rect.y -= self.rect.w - elif rotation.value == Rotations.EAST.value: - self.rect.x += self.rect.w - elif rotation.value == Rotations.SOUTH.value: - self.rect.y += self.rect.w - elif rotation.value == Rotations.WEST.value: - self.rect.x -= self.rect.w + if rotation.value == Rotations.NORTH.value: + self.rect.y -= self.rect.w + elif rotation.value == Rotations.EAST.value: + self.rect.x += self.rect.w + elif rotation.value == Rotations.SOUTH.value: + self.rect.y += self.rect.w + elif rotation.value == Rotations.WEST.value: + self.rect.x -= self.rect.w def rotate(self, rotation): - self.image = pygame.transform.rotate(self.image, ((self.rotation.value - rotation.value) * 90)) - self.rotation = rotation - + # 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: + self.image = pygame.transform.rotate(self.image, ((self.rotation.value - rotation.value) * 90)) + self.rotation = rotation class Rotations(Enum): NORTH = 0 diff --git a/src/game/EventManager.py b/src/game/EventManager.py index d2a9a13..540b60d 100644 --- a/src/game/EventManager.py +++ b/src/game/EventManager.py @@ -7,6 +7,7 @@ TIMEOUT = 100 class EventManager: keyTimeout = 0 + #self.game.map def __init__(self, gameObject, player): self.game = gameObject self.player = player @@ -34,11 +35,21 @@ class EventManager: # TODO: Load key bindings from JSON if keys[pygame.K_w]: - self.player.move(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): + self.player.move(Rotations.NORTH) if keys[pygame.K_s]: - self.player.move(Rotations.SOUTH) + self.player.rotate(Rotations.SOUTH) + if not self.game.map.collision(self.player.rect.x, self.player.rect.y + self.player.rect.w): + self.player.move(Rotations.SOUTH) if keys[pygame.K_d]: - self.player.move(Rotations.EAST) + self.player.rotate(Rotations.EAST) + if not self.game.map.collision(self.player.rect.x + self.player.rect.w, self.player.rect.y): + self.player.move(Rotations.EAST) if keys[pygame.K_a]: - self.player.move(Rotations.WEST) + self.player.rotate(Rotations.WEST) + if not self.game.map.collision(self.player.rect.x - self.player.rect.w, self.player.rect.y): + self.player.move(Rotations.WEST) + + diff --git a/src/game/Game.py b/src/game/Game.py index 6e6e8e4..88f4647 100644 --- a/src/game/Game.py +++ b/src/game/Game.py @@ -6,6 +6,7 @@ from os import path from game.EventManager import EventManager from game.Screen import Screen from game.Map import Map +from src.entities.Player import Player class Game: @@ -27,6 +28,7 @@ class Game: print("Initializing pygame...", end=" ") pygame.init() self.spritesList = pygame.sprite.Group() + print("OK") print("Initializing screen, params: " + str(self.config["window"]) + "...", end=" ") @@ -38,12 +40,11 @@ class Game: self.screen = Screen(self, self.config["window"]) print("OK") - self.eventManager = EventManager(self) - - # Start Map implement self.mapDataFolder = path.dirname("../data/mapdata/") self.map = Map(path.join(self.mapDataFolder, 'map.txt'), self.screen) - # End Map implement + self.player = Player((0, 0), self.map.tileSize) + self.map.addEntity(self.player) + self.eventManager = EventManager(self, self.player) self.mainLoop() diff --git a/src/game/Map.py b/src/game/Map.py index 7daa356..82a498f 100644 --- a/src/game/Map.py +++ b/src/game/Map.py @@ -6,7 +6,9 @@ class Map: def __init__(self, filename, screen): self.screen = screen self.terrain = [] - self.entities = [] + self.collidableTerrain = [] + self.collidables = pygame.sprite.Group() + with open(filename, 'rt') as f: for line in f: self.terrain.append(line) @@ -19,15 +21,26 @@ class Map: self.height = self.tileHeight * self.tileSize self.terrainDraw() - + def terrainDraw(self): for row, tiles in enumerate(self.terrain): for col, tile in enumerate(tiles): if tile == 'w': - self.screen.draw(TerrainTile('wall.png', self.tileSize), Locations.MAP, col*self.tileSize, row*self.tileSize) + object = TerrainTile(col, row, 'wall.png', self.tileSize) + self.screen.draw(object, Locations.MAP, 0, 0) + self.collidables.add(object) elif tile == ',': - self.screen.draw(TerrainTile('floor.png', self.tileSize), Locations.MAP, col*self.tileSize, row*self.tileSize) + self.screen.draw(TerrainTile(col, row, 'floor.png', self.tileSize), Locations.MAP, 0, 0) elif tile == '.': - self.screen.draw(TerrainTile('grass.png', self.tileSize), Locations.MAP, col*self.tileSize, row*self.tileSize) - + self.screen.draw(TerrainTile(col, row, 'grass.png', self.tileSize), Locations.MAP, 0, 0) + def addEntity(self, entity): + self.screen.draw(entity, Locations.MAP, 0, 0) + self.collidables.add(entity) + + # add object to map.collidables list to be collidable + def collision(self, x, y): + for b in self.collidables: + if b.rect.x == x and b.rect.y == y: + return True + return False diff --git a/src/game/TerrainTile.py b/src/game/TerrainTile.py index 636838b..064c303 100644 --- a/src/game/TerrainTile.py +++ b/src/game/TerrainTile.py @@ -4,10 +4,14 @@ from os import path class TerrainTile(pygame.sprite.Sprite): - def __init__(self, texture, tileSize): + def __init__(self, x, y, texture, tileSize): super().__init__() self.imagesFolder = path.dirname("../data/images/") self.terrainFolder = path.join(self.imagesFolder, 'terrain') self.image = pygame.image.load(os.path.join(self.terrainFolder, texture)).convert() self.image = pygame.transform.scale(self.image, (tileSize, tileSize)) self.rect = self.image.get_rect() + self.x = x + self.y = y + self.rect.x = x * tileSize + self.rect.y = y * tileSize diff --git a/src/game/Timer.py b/src/game/Timer.py index 4fbc44b..07496c9 100644 --- a/src/game/Timer.py +++ b/src/game/Timer.py @@ -1,4 +1,66 @@ +import pygame + +# Timer class for the game +# We count time every second, an the time elapsed in game is 60 times the actual time +# So, if we spend 60 seconds, we count that we spent 60 minutes. + +# Day/night cycle parameters +DAY_START = "7:00" +NIGHT_START = "22:00" + + class Timer: - def __init__(self): - self.time - self.cycle + def __init__(self, startTime="12:00"): + self.clock = pygame.time.Clock() + + # Time in milliseconds updated every frame, starts counting from what we specify as a parameter + self.timePassed = self.timeToMs(startTime) + # You have to start the clock manually by calling startClock() method + self.isStarted = False + + def startClock(self): + self.isStarted = True + + def stopClock(self): + self.isStarted = False + + # Returns a string with formatted time + def getPrettyTime(self): + # 60 times faster than real time + minutes = int(self.timePassed / 1000) % 60 + hours = int(self.timePassed / 60000) % 24 + + # Add 0's at the beginning if necessary + prefixHr = "" + prefixMin = "" + if len(str(hours)) < 2: + prefixHr = "0" + if len(str(minutes)) < 2: + prefixMin = "0" + + # Return a formatted time + return prefixHr + str(hours) + ":" + prefixMin + str(minutes) + + # Returns true, if it's daytime + def isItDay(self): + if self.timeToMs(DAY_START) < self.timePassed < self.timeToMs(NIGHT_START): + return True + else: + return False + + # Called every frame to update the timer + def updateTime(self, elapsed): + # Only happens if the time is set to be running + if self.isStarted: + # Modulo, since we use the 24-hour cycle + # In our case, the time loops every 24 minutes + self.timePassed =(self.timePassed + elapsed) % 1440000 + + # Converts time as string to integer milliseconds + def timeToMs(self, timeString): + timeList = timeString.split(':') + hours = timeList[0] + minutes = timeList[1] + return int(hours) * 60000 + int(minutes) * 1000 + +