Things can now be shared globally by maps.
This commit is contained in:
parent
aba0014e27
commit
963c77f77c
3 changed files with 73 additions and 35 deletions
11
gamebase.py
11
gamebase.py
|
@ -44,7 +44,7 @@ class GameBase(object):
|
||||||
self.eventQueue = []
|
self.eventQueue = []
|
||||||
self.gameTime = 0.0
|
self.gameTime = 0.0
|
||||||
self.skipLoop = True
|
self.skipLoop = True
|
||||||
self.nextThing = 0
|
self.nextThing = 1
|
||||||
|
|
||||||
# player info
|
# player info
|
||||||
self.playerName = 'You'
|
self.playerName = 'You'
|
||||||
|
@ -363,9 +363,9 @@ Object can be the name of the object, or its coordinates."""
|
||||||
|
|
||||||
# load the new level
|
# load the new level
|
||||||
if len(args) == 2:
|
if len(args) == 2:
|
||||||
self.level, self.nextThing = _gm.GameMap.read(args[0], int(args[1]), preLoaded, self.nextThing)
|
self.level, self.nextThing = _gm.GameMap.read(args[0], int(args[1]), self.singletons, preLoaded, self.nextThing)
|
||||||
else:
|
else:
|
||||||
self.level, self.nextThing = _gm.GameMap.read(args[0], None, preLoaded, self.nextThing)
|
self.level, self.nextThing = _gm.GameMap.read(args[0], None, self.singletons, preLoaded, self.nextThing)
|
||||||
|
|
||||||
if self.level == None:
|
if self.level == None:
|
||||||
raise GameError("Map could not be loaded.")
|
raise GameError("Map could not be loaded.")
|
||||||
|
@ -388,7 +388,7 @@ Object can be the name of the object, or its coordinates."""
|
||||||
inventory = {}, customValues = {}, name = self.playerName)
|
inventory = {}, customValues = {}, name = self.playerName)
|
||||||
#print("Player created.")
|
#print("Player created.")
|
||||||
else:
|
else:
|
||||||
self.player.x, self.player.y = x, y
|
self.player.x, self.player.y = mx, my
|
||||||
#print("Player moved.")
|
#print("Player moved.")
|
||||||
self.player.prevx, self.player.prevy = self.player.x, self.player.y
|
self.player.prevx, self.player.prevy = self.player.x, self.player.y
|
||||||
self.nextThing = self.level.addThing(self.player, self.nextThing) # The player needs to be added to the new level.
|
self.nextThing = self.level.addThing(self.player, self.nextThing) # The player needs to be added to the new level.
|
||||||
|
@ -559,6 +559,7 @@ Object can be the name of the object, or its coordinates."""
|
||||||
# any map. This is useful for when you have major characters who will
|
# any map. This is useful for when you have major characters who will
|
||||||
# show up in many scenes, and their inventory must stay the same, for
|
# show up in many scenes, and their inventory must stay the same, for
|
||||||
# example.
|
# example.
|
||||||
|
self.singletons = {}
|
||||||
if 'singletons' in data:
|
if 'singletons' in data:
|
||||||
for thing in data['singletons']:
|
for thing in data['singletons']:
|
||||||
#thing = data['singletons'][datum]
|
#thing = data['singletons'][datum]
|
||||||
|
@ -576,7 +577,7 @@ Object can be the name of the object, or its coordinates."""
|
||||||
self.nextThing = _gm.GameMap.addThingRecursive(i.customValues, self.nextThing + 1)
|
self.nextThing = _gm.GameMap.addThingRecursive(i.customValues, self.nextThing + 1)
|
||||||
thing.addThing(i)
|
thing.addThing(i)
|
||||||
del thing.tempInventory
|
del thing.tempInventory
|
||||||
self.singletons = list(data['singletons'])
|
self.singletons[thing.name] = thing
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def gameEventLoop(self):
|
def gameEventLoop(self):
|
||||||
|
|
54
gamemap.py
54
gamemap.py
|
@ -5,6 +5,38 @@ import ruamel.yaml
|
||||||
import math as _mt
|
import math as _mt
|
||||||
import gamethings as _gt
|
import gamethings as _gt
|
||||||
import gamelocus as _gl
|
import gamelocus as _gl
|
||||||
|
from ruamel.yaml.comments import CommentedMap
|
||||||
|
|
||||||
|
class Singleton(object):
|
||||||
|
"""This is a super basic class (would be a struct in other languages)
|
||||||
|
that represents where a singleton Thing should be in a map."""
|
||||||
|
yaml_flag = u'!Singleton'
|
||||||
|
|
||||||
|
def __init__(self, name: str, x: int, y: int):
|
||||||
|
self.name = name
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_yaml(cls, representer, node):
|
||||||
|
representer.represent_mapping({
|
||||||
|
'name': self.name,
|
||||||
|
'location': (self.x, self.y)
|
||||||
|
})
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_yaml(cls, constructor, node):
|
||||||
|
parts = CommentedMap()
|
||||||
|
constructor.construct_mapping(node, parts, True)
|
||||||
|
# since all parts are necessary, I won't bother with if statements
|
||||||
|
# and let it crash.
|
||||||
|
if not isinstance(parts['name'], str):
|
||||||
|
raise RuntimeError("Name must be a string.")
|
||||||
|
if not isinstance(parts['location'], list):
|
||||||
|
raise RuntimeError("Location must be a list.")
|
||||||
|
if not (isinstance(parts['location'][0], int) and isinstance(parts['location'][1], int)):
|
||||||
|
raise RuntimeError("Coordinates must be integers.")
|
||||||
|
return cls(parts['name'], parts['location'][0], parts['location'][1])
|
||||||
|
|
||||||
class MapError(RuntimeError):
|
class MapError(RuntimeError):
|
||||||
pass
|
pass
|
||||||
|
@ -24,6 +56,7 @@ class GameMap(object):
|
||||||
yaml.register_class(_gt.Door)
|
yaml.register_class(_gt.Door)
|
||||||
yaml.register_class(_gt.MapExit)
|
yaml.register_class(_gt.MapExit)
|
||||||
yaml.register_class(_gt.MapEntrance)
|
yaml.register_class(_gt.MapEntrance)
|
||||||
|
yaml.register_class(Singleton)
|
||||||
|
|
||||||
def __init__(self, name, graph, matrix, dimensions):
|
def __init__(self, name, graph, matrix, dimensions):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -63,7 +96,7 @@ class GameMap(object):
|
||||||
return text.replace('\n', end)
|
return text.replace('\n', end)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def read(infile = None, prevMap = None, preLoaded = False, nextThing = 0):
|
def read(infile = None, prevMap = None, singletons = None, preLoaded = False, nextThing = 0):
|
||||||
"""Read map data and return a Map object. If infile is not provided, then
|
"""Read map data and return a Map object. If infile is not provided, then
|
||||||
it will read from stdin. Otherwise, it should be a valid file name.
|
it will read from stdin. Otherwise, it should be a valid file name.
|
||||||
Entering a map through stdin will be obsolete once testing is over."""
|
Entering a map through stdin will be obsolete once testing is over."""
|
||||||
|
@ -106,7 +139,7 @@ Entering a map through stdin will be obsolete once testing is over."""
|
||||||
level = GameMap(infile, mapGraph, mapMatrix, dimensions)
|
level = GameMap(infile, mapGraph, mapMatrix, dimensions)
|
||||||
|
|
||||||
# Now, load other info
|
# Now, load other info
|
||||||
nextThing = GameMap.loadThings(level, info, prevMap, preLoaded, nextThing)
|
nextThing = GameMap.loadThings(level, info, prevMap, singletons, preLoaded, nextThing)
|
||||||
|
|
||||||
return level, nextThing
|
return level, nextThing
|
||||||
|
|
||||||
|
@ -171,7 +204,7 @@ list of lists of tuples."""
|
||||||
return mat, graph, dim
|
return mat, graph, dim
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def loadThings(level, info, prevMap = None, preLoaded = False, nextThing = 0):
|
def loadThings(level, info, prevMap = None, singletons = None, preLoaded = False, nextThing = 0):
|
||||||
"""load the things from the xml part of the map file."""
|
"""load the things from the xml part of the map file."""
|
||||||
if 'openingText' in info:
|
if 'openingText' in info:
|
||||||
level.openingText = info['openingText']
|
level.openingText = info['openingText']
|
||||||
|
@ -197,20 +230,32 @@ list of lists of tuples."""
|
||||||
if 'loadOnce' in info and not preLoaded:
|
if 'loadOnce' in info and not preLoaded:
|
||||||
for thing in info['loadOnce']:
|
for thing in info['loadOnce']:
|
||||||
#print(type(thing))
|
#print(type(thing))
|
||||||
|
if isinstance(thing, _gt.Thing):
|
||||||
nextThing = level.addThing(thing, nextThing, True)
|
nextThing = level.addThing(thing, nextThing, True)
|
||||||
|
else:
|
||||||
|
raise MapError("Non-thing loaded as a thing:\n{}".format(thing))
|
||||||
if 'loadAlways' in info:
|
if 'loadAlways' in info:
|
||||||
for thing in info['loadAlways']:
|
for thing in info['loadAlways']:
|
||||||
#print(type(thing))
|
#print(type(thing))
|
||||||
|
if isinstance(thing, _gt.Thing):
|
||||||
nextThing = level.addThing(thing, nextThing)
|
nextThing = level.addThing(thing, nextThing)
|
||||||
if ((thing.thingType == 'x' and not hasKnownEntrance) or thing.thingType == 'a') and prevMap == thing.exitid:
|
if ((thing.thingType == 'x' and not hasKnownEntrance) or thing.thingType == 'a') and prevMap == thing.exitid:
|
||||||
level.playerStart = (thing.x, thing.y)
|
level.playerStart = (thing.x, thing.y)
|
||||||
hasKnownEntrance = True
|
hasKnownEntrance = True
|
||||||
|
elif isinstance(thing, Singleton):
|
||||||
|
if singletons != None:
|
||||||
|
single = singletons[thing.name]
|
||||||
|
single.x, single.y = thing.x, thing.y
|
||||||
|
single.prevx, single.prevy = thing.x, thing.y
|
||||||
|
nextThing = level.addThing(single, nextThing)
|
||||||
|
else:
|
||||||
|
raise MapError("Non-thing loaded as a thing:\n{}".format(thing))
|
||||||
return nextThing
|
return nextThing
|
||||||
|
|
||||||
# stuff the gameshell itself might use
|
# stuff the gameshell itself might use
|
||||||
|
|
||||||
def addThing(self, thing, nextThing = 0, persist = False):
|
def addThing(self, thing, nextThing = 0, persist = False):
|
||||||
if thing == None:
|
if thing == None: # it must be a singleton
|
||||||
return nextThing
|
return nextThing
|
||||||
#if thing.name in self.thingNames: # resolved
|
#if thing.name in self.thingNames: # resolved
|
||||||
# raise ValueError("Cannot have two objects named {0}.".format(thing.name))
|
# raise ValueError("Cannot have two objects named {0}.".format(thing.name))
|
||||||
|
@ -219,6 +264,7 @@ list of lists of tuples."""
|
||||||
nextThing += 1
|
nextThing += 1
|
||||||
# Some things, like containers, have other things as custom values,
|
# Some things, like containers, have other things as custom values,
|
||||||
# so they need IDs as well.
|
# so they need IDs as well.
|
||||||
|
# Let's only add them if they weren't already loaded.
|
||||||
if thing.thingType in 'iun':
|
if thing.thingType in 'iun':
|
||||||
nextThing = GameMap.addThingRecursive(thing.customValues, nextThing)
|
nextThing = GameMap.addThingRecursive(thing.customValues, nextThing)
|
||||||
if thing.thingType == 'n':
|
if thing.thingType == 'n':
|
||||||
|
|
|
@ -51,15 +51,6 @@ loadAlways:
|
||||||
none: none # might this work to prevent this character from doing anything?
|
none: none # might this work to prevent this character from doing anything?
|
||||||
customValues:
|
customValues:
|
||||||
dialogs: testing/testDialog.yml
|
dialogs: testing/testDialog.yml
|
||||||
- !NPC
|
- !Singleton
|
||||||
name: follower
|
name: follower
|
||||||
description: a follower
|
|
||||||
location: [6, 26]
|
location: [6, 26]
|
||||||
behaviors:
|
|
||||||
go: [-1, follow]
|
|
||||||
arrive: [-1, follow]
|
|
||||||
customValues:
|
|
||||||
follow:
|
|
||||||
distance: 2
|
|
||||||
isFollowing: True
|
|
||||||
target: You # yes, YOU!
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue