-
Notifications
You must be signed in to change notification settings - Fork 17
Image based Maps
In this approach to mapping, you create a map in your preferred drawing package, and Quest will display it on the page, with a marker indicating the player position. It can be set up so that the user can use the mouse wheel to scroll in and out, and drag to move; the map will re-centre after every command. Alternatively, the user can click on "hot-spots" on the map, and these can be set up to run a function, parse a certain command or move the player.
The first thing you need is the image.
You have a number of options; I recommend GIMP if you want a pixel editor or Inkscape for vector graphics, as both have a lot of features and both are free; they are both available on Windows, macOS and Linux. Alternatively, draw it on paper, and scan it into your computer. The file should be a format browsers will all handle, so PNG, JPG/JPEG or SVG are best.
I suggest a lot of space around your map, as the player will sometimes be visiting the outer lying locations. You might want to divide the image into thirds, both horizontally and vertically, and do all your drawing in the central block. I would recommend making your image at least 1000 pixels on each side.
You might want to get a fancy background, like the ancient paper in the image above. Make sure the image is royalty free and has no watermarks, and is of a high enough resolution. Have the background on one layer, and draw on another layer, so you can erase mistakes. For the above, I used a GIMP paintbrush that varied the pen and dark brown rather than black to make it more like it was hand-drawn.
You need to tell Quest to import the library file.
settings.libraries.push('image-map')
There are then a number of settings. The most import is the "mapImages" attribute. This is an array of dictionaries, with each element of the array corresponding to a map image. In this example, two map images are used. Each needs a filename (with path and extension), the width and height of the image in pixels, and the name.
settings.mapImages = [
{
name:'Halmuth',
file:'game-alt-map/halmuth.png',
width:1000,
height:1000,
},
{
name:'Small scale',
file:'game-alt-map/country.png',
width:1000,
height:1000,
},
]
These are optional settings to customise it:
settings.mapScrollSpeed = 1
settings.mapStyle = {
right:'0',
top:'200px',
width:'400px',
height:'400px',
'background-color':'#ddd',
border:'3px black solid',
}
settings.mapMarker = function(loc) {
return map.polygon(loc, [
[0,0], [-5,-25], [-7, -20], [-18, -45], [-20, -40], [-25, -42], [-10, -18], [-15, -20]
], 'stroke:none;fill:black;pointer-events:none;opacity:0.5')
}
The first determines how fast the map scrolls. The next two determine how the map itself and the scroll arrows are displayed, while the last is used to draw the marker.
Having done that, the locations are very easy - you just need to set their x and y values. Note that the coordinates start in the top left corner of the map.
createRoom("street_of_the_gods", {
desc:"The street is boring, the author really needs to put stuff in it.",
west:new Exit('museum_of_curios'),
mapX:400,
mapY:450,
})
createRoom("museum_of_curios", {
desc:"The museum is boring, the author really needs to put stuff in it.",
east:new Exit('street_of_the_gods'),
up:new Exit('museum_of_curios_upstairs'),
mapX:300,
mapY:480,
})
createRoom("museum_of_curios_upstairs", {
desc:"The upper level of the museum is boring, the author really needs to put stuff in it.",
down:new Exit('museum_of_curios'),
})
If a location has no coordinates, Quest will assume they are the same as the previous room. You MUST set the coordinates for the starting location.
You can also set the "mapRegion" attribute if this is the first location on a different map. This should be the name you gave the map in settings.mapImages
. If you do not set this for the starting location, Quest will use the first one in the list.
You can flag points on the map to let the player know it is somewhere to go. For example, if the player is given a quest to get the Eye of Dathmir, you could flag on the map of the land what city she needs to go to, and then on the city map flag which building to search.
These locations are set in an array called settings.mapPointsOfInterest
. If the point is not on the first map, you need to set the mapRegion. You also need to set the coordinates, the fill colour and, of course, the text.
settings.mapPointsOfInterest = [
{mapX:620, mapY:470, fill:'red', text:'Eye of Dathmi'},
{mapX:140, mapY:830, mapRegion:'Small scale', fill:'red', text:'Eye of Dathmi'},
]
That will be here for the entire game. You might want it only to appear once the player has been asked to get the thing, and to disappear once she has it. This can be done by adding an "isActive" attribute, a function that returns true
only when the marker should appear. Remember that only objects in the world are saved, so the quest state has to be stored on such an object; in this example on the eye itself.
settings.mapPointsOfInterest = [
{
mapX:620, mapY:470, fill:'red',
text:'Eye of Dathmi',
isActive:function() { return w.eye_of_dathmir.questActive },
},
{
mapX:140, mapY:830, mapRegion:'Small scale', fill:'red',
text:'Eye of Dathmi',
isActive:function() { return w.eye_of_dathmir.questActive },
},
]
The above gives you a map that can be dragged around and zoomed. The alternative approach is a map with hot-spots the user can click to make something happen.
To do that, set up some map regions, in settings.js. This example creates four hot-spots, illustratng the four different types. The first has "w" and "h", this creates a reactangle with the given width and height. The second with "r" gives a circle with the given radius. The third, with "rx" and "ry", gives an ellipse, whilst the last is a series of points defining a polygon that can be any shape you want.
settings.mapRegions = [
{x:500, y:300, w:50, h:30, script:function() {log('blue!')}},
{x:300, y:300, r:30, fill:'red', jump:'wheat_road'},
{x:400, y:400, rx:20, ry:50, fill:'green', cmd:'get hat'},
{pts:'400,500, 480,500 440,560', fill:'yellow', script:function() {log('yellow!')}},
]
Regions default to blue, but you can set them to any colour with the "fill" attribute. You may want them to be invisible, but setting them to a colour ca be useful when setting up so you can see if there are in the right place.
This brings us to our next setting...
settings.mapRegionOpacity = 0.5
This defines where we can see though the shapes that make up the regions. A value of 1 will be opaque, and value of 0 with make them invisible.
So what can we do with a region?
If a region has a "script" attribute, this function will be run when the user clicks on the hotspot.
Otherwise, if a region has a "jump" attribute, the player will be moved to the location named. This will be as though the player used an exit with the direction "teleport".
Otherwise, if a region has a "cmd" attribute, the given string will be given to the parser exactly as though the user have typed it.
To be able to handle the "jump" option, you might want to change the value of lang.go_successful
. You can detect if this was a teleport, rather than using a directional exit.
lang.go_successful = "{if:exit:dir:teleport:Teleport!:{nv:char:head:true} {show:dir}.}"
Note that you can add "isActive" attributes to regions just as with points of interest.
Tutorial
- First steps
- Rooms and Exits
- Items
- Templates
- Items and rooms again
- More items
- Locks
- Commands
- Complex mechanisms
- Uploading
QuestJS Basics
- General
- Settings
- Attributes for items
- Attributes for rooms
- Attributes for exits
- Naming Items and Rooms
- Restrictions, Messages and Reactions
- Creating objects on the fly
- String Functions
- Random Functions
- Array/List Functions
- The
respond
function - Other Functions
The Text Processor
Commands
- Introduction
- Basic commands (from the tutorial)
- Complex commands
- Example of creating a command (implementing SHOOT GUN AT HENRY)
- More on commands
- Shortcut for commands
- Modifying existing commands
- Custom parser types
- Note on command results
- Meta-Commands
- Neutral language (including alternatives to "you")
- The parser
- Command matching
- Vari-verbs (for verbs that are almost synonyms)
Templates for Items
- Introduction
- Takeable
- Openable
- Container and surface
- Locks and keys
- Wearable
- Furniture
- Button and Switch
- Readable
- Edible
- Vessel (handling liquids)
- Components
- Countable
- Consultable
- Rope
- Construction
- Backscene (walls, etc.)
- Merchandise (including how to create a shop)
- Shiftable (can be pushed from one room to another)
See also:
- Custom templates (and alternatives)
Handing NPCs
- Introduction
- Attributes
- Allowing the player to give commands
- Conversations
- Simple TALK TO
- SAY
- ASK and TELL
- Dynamic conversations with TALK TO
- TALK and DISCUSS
- Following an agenda
- Reactions
- Giving
- Followers
- Visibility
- Changing the player point-of-view
The User Experience (UI)
The main screen
- Basics
- Printing Text Functions
- Special Text Effects
- Output effects (including pausing)
- Hyperlinks
- User Input
The Side Panes
Multi-media (sounds, images, maps, etc.)
- Images
- Sounds
- Youtube Video (Contribution by KV)
- Adding a map
- Node-based maps
- Image-based maps
- Hex maps
- Adding a playing board
- Roulette!... in a grid
Dialogue boxes
- Character Creation
- Other example dialogs [See also "User Input"]
Other Elements
- Toolbar (status bar across the top)
- Custom UI Elements
Role-playing Games
- Introduction
- Getting started
- Items
- Characters (and Monsters!)
- Spawning Monsters and Items)
- Systema Naturae
- Who, When and How NPCs Attack
- Attributes for characters
- Attacking and guarding
- Communicating monsters
- Skills and Spells
- Limiting Magic
- Effects
- The Attack Object
- [Extra utility functions](https://github.com/ThePix/QuestJS/wiki/RPG-Library-%E2%80%90-Extra Functions)
- Randomly Generated Dungeon
- Quests for Quest
- User Interface
Web Basics
- HTML (the basic elements of a web page)
- CSS (how to style web pages)
- SVG (scalable vector graphics)
- Colours
- JavaScript
- Regular Expressions
How-to
Time
- Events (and Turnscripts)
- Date and Time (including custom calendars)
- Timed Events (i.e., real time, not game time)
Items
- Phone a Friend
- Using the USE verb
- Display Verbs
- Change Listeners
- Ensembles (grouping items)
- How to spit
Locations
- Large, open areas
- Region,s with sky, walls, etc.
- Dynamic Room Descriptions
- Transit system (lifts/elevators, buses, trains, simple vehicles)
- Rooms split into multiple locations
- Create rooms on the fly
- Handling weather
Exits
- Alternative Directions (eg, port and starboard)
- Destinations, Not Directions
Meta
- Customise Help
- Provide hints
- Include Achievements
- Add comments to your code
-
End The Game (
io.finish
)
Meta: About The Whole Game
- Translate from Quest 5
- Authoring Several Games at Once
- Chaining Several Games Together
- Competition Entry
- Walk-throughs
- Unit testing
- Debugging (trouble-shooting)
Releasing Your Game
Reference
- The Language File
- List of settings
- Scope
- The Output Queue
- Security
- Implementation notes (initialisation order, data structures)
- Files
- Code guidelines
- Save/load
- UNDO
- The editor
- The Cloak of Darkness
- Versions
- Quest 6 or QuestJS
- The other Folders
- Choose your own adventure