1- import datetime
21from math import ceil , floor
3- import time
42import pygame
5- from apple import Apple
6- from grid import Grid
7- from location import Location
8- from wood import Wood
93from config import Config
10- from food import Food
114from graphik import Graphik
12- from grass import Grass
13- from leaves import Leaves
14- from map import Map
15- from player import Player
165from status import Status
6+ from worldScreen import WorldScreen
177
188
199# @author Daniel McCoy Stephenson
2010# @since August 8th, 2022
2111class Roam :
2212 def __init__ (self ):
23- self .config = Config ()
24- self .running = True
25- self .tick = 0
2613 pygame .init ()
2714 pygame .display .set_caption ("Roam" )
28- self .initializeGameDisplay ()
2915 pygame .display .set_icon (pygame .image .load ('src/icon.PNG' ))
16+ self .config = Config ()
17+ self .running = True
18+ self .tick = 0
19+ self .gameDisplay = self .initializeGameDisplay ()
3020 self .graphik = Graphik (self .gameDisplay )
31- self .map = Map (self .config .gridSize , self .graphik )
32- self .currentRoom = self .map .getSpawnRoom ()
33- self .initializeLocationWidthAndHeight ()
34- self .player = Player ()
35- self .score = 0
36- self .numApplesEaten = 0
3721 self .status = Status (self .graphik )
3822 self .status .set ("entered the world" , self .tick )
39- self .numDeaths = 0
23+ self .worldScreen = WorldScreen ( self . graphik , self . config , self . status , self . tick )
4024
4125 def initializeGameDisplay (self ):
4226 if self .config .fullscreen :
43- self . gameDisplay = pygame .display .set_mode ((self .config .displayWidth , self .config .displayHeight ), pygame .FULLSCREEN )
27+ return pygame .display .set_mode ((self .config .displayWidth , self .config .displayHeight ), pygame .FULLSCREEN )
4428 else :
45- self .gameDisplay = pygame .display .set_mode ((self .config .displayWidth , self .config .displayHeight ), pygame .RESIZABLE )
46-
47- def initializeLocationWidthAndHeight (self ):
48- x , y = self .gameDisplay .get_size ()
49- self .locationWidth = x / self .currentRoom .getGrid ().getRows ()
50- self .locationHeight = y / self .currentRoom .getGrid ().getColumns ()
51-
52- def printStats (self ):
53- print ("=== Stats ===" )
54- print ("Rooms Explored: " + str (len (self .map .getRooms ())) + "/" + str ((self .config .worldBorder + 1 )* (self .config .worldBorder + 1 )))
55- print ("Apples eaten: " + str (self .numApplesEaten ))
56- print ("Items in inventory: " + str (len (self .player .getInventory ().getContents ())))
57- print ("Number of deaths: " + str (self .numDeaths ))
58- print ("" )
59- print ("Score: " + str (self .score ))
60- print ("----------" )
29+ return pygame .display .set_mode ((self .config .displayWidth , self .config .displayHeight ), pygame .RESIZABLE )
6130
6231 def quitApplication (self ):
63- self .printStats ()
6432 pygame .quit ()
6533 quit ()
66-
67- def getLocationOfPlayer (self ):
68- return self .map .getLocation (self .player , self .currentRoom )
69-
70- def getLocationDirection (self , direction : int , grid : Grid , location : Location ):
71- if direction == 0 :
72- return grid .getUp (location )
73- elif direction == 1 :
74- return grid .getLeft (location )
75- elif direction == 2 :
76- return grid .getDown (location )
77- elif direction == 3 :
78- return grid .getRight (location )
79-
80- def getCoordinatesForNewRoomBasedOnPlayerLocation (self ):
81- location = self .getLocationOfPlayer ()
82- x = self .currentRoom .getX ()
83- y = self .currentRoom .getY ()
84- if location .getX () == self .config .gridSize - 1 :
85- # we are on the right side of this room
86- x += 1
87- elif location .getX () == 0 :
88- # we are on the left side of this room
89- x -= 1
90- elif location .getY () == self .config .gridSize - 1 :
91- # we are at the bottom of this room
92- y += 1
93- elif location .getY () == 0 :
94- # we are at the top of this room
95- y -= 1
96- return x , y
97-
98- def changeRooms (self ):
99- x , y = self .getCoordinatesForNewRoomBasedOnPlayerLocation ()
100-
101- if abs (x ) > self .config .worldBorder or abs (y ) > self .config .worldBorder :
102- self .status .set ("reached world border" , self .tick )
103- return
104-
105- playerLocation = self .getLocationOfPlayer ()
106- self .currentRoom .removeEntity (self .player )
107-
108- room = self .map .getRoom (x , y )
109- if room == - 1 :
110- x , y = self .getCoordinatesForNewRoomBasedOnPlayerLocation ()
111- self .currentRoom = self .map .generateNewRoom (x , y )
112- self .status .set ("new area discovered" , self .tick )
113- else :
114- self .currentRoom = room
115-
116- targetX = playerLocation .getX ()
117- targetY = playerLocation .getY ()
118-
119- min = 0
120- max = self .config .gridSize - 1
121- if playerLocation .getY () == min :
122- targetY = max
123- elif playerLocation .getY () == max :
124- targetY = min
125-
126- if playerLocation .getX () == min :
127- targetX = max
128- elif playerLocation .getX () == max :
129- targetX = min
130-
131- targetLocation = self .currentRoom .getGrid ().getLocationByCoordinates (targetX , targetY )
132- self .currentRoom .addEntityToLocation (self .player , targetLocation )
133- self .initializeLocationWidthAndHeight ()
134- pygame .display .set_caption (("Roam " + str (self .currentRoom .getName ())))
135-
136- def movePlayer (self , direction : int ):
137- if direction == - 1 :
138- return
139-
140- location = self .getLocationOfPlayer ()
141- newLocation = self .getLocationDirection (direction , self .currentRoom .getGrid (), location )
142-
143- if newLocation == - 1 :
144- # we're at a border
145- self .changeRooms ()
146- return
147-
148- if self .map .locationContainsEntity (newLocation , Wood ):
149- # apple trees are solid
150- return
151-
152- # search for food
153- for entity in newLocation .getEntities ():
154- if isinstance (entity , Food ):
155- newLocation .removeEntity (entity )
156- scoreIncrease = 1 * len (self .map .getRooms ())
157- self .score += scoreIncrease
158- self .player .addEnergy (entity .getEnergy ())
159-
160- if isinstance (entity , Apple ):
161- self .numApplesEaten += 1
162- self .status .set ("ate '" + entity .getName () + "'" , self .tick )
163-
164- # move player
165- location .removeEntity (self .player )
166- newLocation .addEntity (self .player )
16734
168- # decrease energy
169- self .player .removeEnergy (self .config .playerMovementEnergyCost )
170-
171- def canBePickedUp (self , entity ):
172- itemTypes = [Wood , Leaves , Grass , Apple ]
173- for itemType in itemTypes :
174- if isinstance (entity , itemType ):
175- return True
176- return False
177-
178- def executeInteractAction (self ):
179- playerLocation = self .getLocationOfPlayer ()
180-
181- toCheck = []
182- toCheck .append (playerLocation )
183- toCheck .append (self .currentRoom .getGrid ().getUp (playerLocation ))
184- toCheck .append (self .currentRoom .getGrid ().getLeft (playerLocation ))
185- toCheck .append (self .currentRoom .getGrid ().getDown (playerLocation ))
186- toCheck .append (self .currentRoom .getGrid ().getRight (playerLocation ))
187-
188- toRemove = - 1
189- for location in toCheck :
190- if location == - 1 :
191- continue
192- reversedEntityList = list (reversed (location .getEntities ()))
193- for entity in reversedEntityList :
194- if self .canBePickedUp (entity ):
195- toRemove = entity
196- break
197- if toRemove != - 1 :
198- break
199-
200- if toRemove == - 1 :
201- return
202-
203- self .currentRoom .removeEntity (toRemove )
204- self .player .getInventory ().place (toRemove )
205- self .status .set ("picked up '" + entity .getName () + "'" , self .tick )
206-
207- def executePlaceAction (self ):
208- if len (self .player .getInventory ().getContents ()) == 0 :
209- self .status .set ("no items" , self .tick )
210- return
211-
212- playerLocation = self .getLocationOfPlayer ()
213- targetLocation = self .currentRoom .getGrid ().getUp (playerLocation )
214- if targetLocation == - 1 :
215- self .status .set ("no location above player" , self .tick )
216- return
217- if self .map .locationContainsEntity (targetLocation , Wood ):
218- self .status .set ("blocked by apple tree" , self .tick )
219- return
220-
221- toPlace = self .player .getInventory ().getContents ().pop ()
222-
223- if toPlace == - 1 :
224- return
225-
226- self .currentRoom .addEntityToLocation (toPlace , targetLocation )
227- self .status .set ("placed '" + toPlace .getName () + "'" , self .tick )
228-
229- # @source https://stackoverflow.com/questions/63342477/how-to-take-screenshot-of-entire-display-pygame
230- def captureScreen (self , name , pos , size ): # (pygame Surface, String, tuple, tuple)
231- image = pygame .Surface (size ) # Create image surface
232- image .blit (self .gameDisplay , (0 ,0 ), (pos , size )) # Blit portion of the display to the image
233- pygame .image .save (image , name ) # Save the image to the disk**
234-
235- def handleKeyDownEvent (self , key ):
236- if key == pygame .K_ESCAPE :
237- self .quitApplication ()
238- elif key == pygame .K_F11 :
239- if self .config .fullscreen :
240- self .config .fullscreen = False
241- else :
242- self .config .fullscreen = True
243- self .initializeGameDisplay ()
244- elif key == pygame .K_l :
245- if self .config .limitTickSpeed :
246- self .config .limitTickSpeed = False
247- else :
248- self .config .limitTickSpeed = True
249- elif key == pygame .K_w or key == pygame .K_UP :
250- self .player .setDirection (0 )
251- elif key == pygame .K_a or key == pygame .K_LEFT :
252- self .player .setDirection (1 )
253- elif key == pygame .K_s or key == pygame .K_DOWN :
254- self .player .setDirection (2 )
255- elif key == pygame .K_d or key == pygame .K_RIGHT :
256- self .player .setDirection (3 )
257- elif key == pygame .K_e :
258- self .player .setInteracting (True )
259- elif key == pygame .K_q :
260- self .player .setPlacing (True )
261- elif key == pygame .K_PRINTSCREEN :
262- x , y = self .gameDisplay .get_size ()
263- self .captureScreen ("screenshot-" + str (datetime .datetime .now ()).replace (" " , "-" ).replace (":" , "." ) + ".png" , (0 ,0 ), (x ,y ))
264- self .status .set ("screenshot saved" , self .tick )
265-
266- def handleKeyUpEvent (self , key ):
267- if (key == pygame .K_w or key == pygame .K_UP ) and self .player .getDirection () == 0 :
268- self .player .setDirection (- 1 )
269- elif (key == pygame .K_a or key == pygame .K_LEFT ) and self .player .getDirection () == 1 :
270- self .player .setDirection (- 1 )
271- elif (key == pygame .K_s or key == pygame .K_DOWN ) and self .player .getDirection () == 2 :
272- self .player .setDirection (- 1 )
273- elif (key == pygame .K_d or key == pygame .K_RIGHT ) and self .player .getDirection () == 3 :
274- self .player .setDirection (- 1 )
275- elif key == pygame .K_e :
276- self .player .setInteracting (False )
277- elif key == pygame .K_q :
278- self .player .setPlacing (False )
279-
280- def respawnPlayer (self ):
281- self .currentRoom .removeEntity (self .player )
282- self .map .getSpawnRoom ().addEntity (self .player )
283- self .currentRoom = self .map .getSpawnRoom ()
284- self .player .energy = self .player .maxEnergy
285- self .player .getInventory ().clear ()
286- self .status .set ("respawned" , self .tick )
287- pygame .display .set_caption (("Roam - " + str (self .currentRoom .getName ())))
288-
289- def displayInfo (self ):
290- x , y = self .gameDisplay .get_size ()
291- startingX = x / 8
292- startingY = y / 8
293- size = 30
294- self .displayEnergy (startingX , startingY , size )
295-
296- def displayEnergy (self , startingX , startingY , size ):
297- self .graphik .drawText ("Energy:" , startingX , startingY - size / 2 , size , self .config .black )
298- self .graphik .drawText (str (floor ((self .player .getEnergy ()))), startingX , startingY + size / 2 , size , self .config .black )
299-
300- def displayInventoryTopItem (self ):
301- x , y = self .gameDisplay .get_size ()
302- xpos = x - x / 8
303- ypos = y / 10
304- size = 15
305- inventory = self .player .getInventory ()
306- if len (inventory .getContents ()) == 0 :
307- return
308- topItem = inventory .getContents ()[- 1 ]
309- self .graphik .drawText ("Next item: " + topItem .getName (), xpos , ypos , size , self .config .black )
310-
31135 def run (self ):
312- self .currentRoom .addEntity (self .player )
313- while self .running :
314- for event in pygame .event .get ():
315- if event .type == pygame .QUIT :
316- self .quitApplication ()
317- elif event .type == pygame .KEYDOWN :
318- self .handleKeyDownEvent (event .key )
319- elif event .type == pygame .KEYUP :
320- self .handleKeyUpEvent (event .key )
321- elif event .type == pygame .WINDOWRESIZED :
322- self .initializeLocationWidthAndHeight ()
323- elif event .type == pygame .VIDEORESIZE :
324- self .simulation .initializeLocationWidthAndHeight ()
325-
326- self .movePlayer (self .player .direction )
327-
328- if self .player .isInteracting ():
329- self .executeInteractAction ()
330- elif self .player .isPlacing ():
331- self .executePlaceAction ()
332-
333- # remove energy and check for death
334- self .player .removeEnergy (0.05 )
335- if self .player .isDead ():
336- self .status .set ("you died" , self .tick )
337- self .score = ceil (self .score * 0.9 )
338- self .numDeaths += 1
339-
340- self .status .checkForExpiration (self .tick )
341-
342- # draw
343- self .gameDisplay .fill (self .currentRoom .getBackgroundColor ())
344- self .currentRoom .draw (self .locationWidth , self .locationHeight )
345- self .status .draw ()
346-
347- # display
348- self .displayInfo ()
349- self .displayInventoryTopItem ()
350-
351- # update
352- pygame .display .update ()
353-
354- if self .config .limitTickSpeed :
355- time .sleep (self .config .tickSpeed )
356- self .tick += 1
357-
358- if self .player .isDead ():
359- time .sleep (3 )
360- self .respawnPlayer ()
361-
362- self .quitApplication ()
36+ self .worldScreen .run ()
36337
36438roam = Roam ()
36539roam .run ()
0 commit comments