I'm needing some direction (more on the lingo side of things) on making a computer game similar to "Riven" or "Myst", The type of game where you walk around Pick up stuff and solve puzzles...
Well, there is no one way to do this, I'll see if I can get you started.
The basic idea of these types of games is that you have an
"environment" built on some type of grid that the user has free
control to walk around and explore. Lets start by looking at the set-up
for the grid itself. Any time you start a project like this make sure to
plan it out on paper first. A little planning at the beginning can save
tons of stress later on. Personally, I like to use number systems, as it
can quickly automate most of the process. I am going to set up a naming
convention for my markers that uses the x position, the y position and the
direction the user is facing. You could do this with graphics and keep it
to one frame, but with puzzles, this can get a little hairy.
My basic marker would then look something like this...
1-1-1
This would be a marker on the grid at 1,1 and facing North. (I use a 4
number system, where 1 is north, 2 is east, etc.) Now that we have our
naming convention, we are ready to start building score and adding markers.
If we were just making 1 or 2 nodes, this would not be a problem, but for a
larger on it can take a lot of time. For this purpose, I have provided a
simple script that will create the markers, name them, and add a "hold on current frame" script for each. Think of it like this. If you have a 5X5 grid with 4 directions on each, do you really want to create 100 frames with 100 instances of a script by hand. Here is the basic score
builder code... (Note that this shoudl be a movie script, not a behavior.)
on buildNavScore numX, numY, holdScriptName
xGrid = integer(numX)
yGrid = integer(numY)
if xGrid > 0 and yGrid > 0 then
beginRecording
go to frame 1
cycle = 0
repeat with x = 1 to xGrid
repeat with y = 1 to yGrid
repeat with z = 1 to 4
the frameLabel = string(x) & "-" & string(y) & "-" & string(z)
go to frame ((cycle * 10) + 5)
the frameScript = member(holdScriptName)
cycle = cycle + 1
go to frame (cycle * 10)
end repeat
end repeat
end repeat
endRecording
end if
end
on getBehaviorDescription me
describe = "This little script is very helpful for generating a basic grid structure for a game that utilizes 4 point nodes. Call like this..." & return & "buildNavScore(numberOfXGridPieces, numberOfYGridPieces, nameOfHoldScript)" return describe
end
For the purposes of this demo, I chose a simple 3X3 grid
and made a "go to the frame" script called "hold", then
typed this in the message window...
buildNavScore(3, 3, "Hold")
A few seconds later, we have our score set up. Now we
need a navigation behavior to move us around in this environment. For this
we can use the last marker we passed to get our current position. I used
the findLastLabel script to get the current marker name. From there we can separate out
each element and move to the correct new location. Below is the behavior I
used to do this. It is dropped on a "hotspot" and can then be
used across every frame. Here is the basic code...
property whichHotSpot, spriteNum
global maxX, maxY
on getPropertyDescriptionList me
p_list = [:]
addProp p_list, #whichHotSpot, [#format : #symbol, #comment : "What navigation hotspot:", #default: #ahead, #range : [#ahead, #turnleft,#turnright, #back]]
return p_list
end
on mouseUp me
--get the current marker
currentLoc = findLastLabel()
--set the delimiter to break the location by
the itemDelimiter = "-"
currentX = integer(currentLoc.item[1])
currentY = integer(currentLoc.item[2])
currentD = integer(currentLoc.item[3])
newLocList = [currentX, currentY, currentD]
case whichHotSpot of
#ahead:
--go foward 1 based upon the current direction
case currentD of
1:
--Facing North
newLocList[2] = (currentY - 1)
if newLocList[2] < 1 then newLocList[2] = 1
2:
--Facing East
newLocList[1] =(currentX + 1)
if newLocList[1] > maxX then newLocList[1] = maxX
3:
--Facing South
newLocList[2] = (currentY + 1)
if newLocList[2] > maxY then newLocList[2] = maxY
4:
--Facing West
newLocList[1] = (currentX - 1)
if newLocList[1] < 1 then newLocList[1] = 1
end case
#turnLeft:
newLocList[3] = currentD - 1
if newLocList[3] < 1 then newLocList[3] = 4
#turnRight:
newLocList[3] = currentD + 1
if newLocList[3] > 4 then newLocList[3] = 1
#back:
case currentD of
1:
--Facing North
newLocList[2] = (currentY + 1)
if newLocList[2] > maxY then newLocList[2] = maxY
2:
--Facing East
newLocList[1] = (currentX + 1)
if newLocList[1] < 1 then newLocList[1] = 1
3:
--Facing South
newLocList[2] = (currentY + 1)
if newLocList[2] < 1 then newLocList[2] = 1
4:
--Facing West
newLocList[1] = (currentX - 1)
if newLocList[1] > maxX then newLocList[1] = maxX
end case
end case
goTo = string(newLocList[1]) & "-" & string(newLocList[2]) & "-" & string(newLocList[3])
if marker(goTo) <> 0 then
go goTo
end if
end
on getBehaviorDescription me
describe = "This behavior can be dropped on hot-spots
to navigate a 3d/Myst like environment. Use the Build Environment Script
to generate the markers for the environment, then set the maxX and maxY
values as globals."
return describe
end
Place this on your hotspots and then set the maxX and maxY globals in your
startMovie handler. This tells the script what the maximum X value and
maximum Y value in the grid is so it will not run beyond its edges.
Technically this could be removed as it also checks for the existence of a
marker before jumping to it, but a little extra error checking never hurt.
If you want a node to be non-existent, just remove its markers.
This is still a pretty simple script. You can add conditions for
skipping markers, making 6 or 8 sided nodes, etc., but this should be a good basic
start.
As for the objects, there are a lot of approaches you can take. You can
add handlers in the first frame of a node to check if the object has been picked
up, and if not, make it visible, but the easiest way (for a few objects) might
be to put each object in a separate channel, then when it is clicked or picked
up, have it added to an inventory list and its channel visibility set to 0.
It will vary for each project, but this is a pretty safe method.
As usual, you can also find all of these behaviors/scripts in the behavior
database.
Contact
MMI
36 South Court Sq
Suite 300
Newnan, GA 30263
USA