Community
SCI Programming => SCI Syntax Help => Topic started by: Cloudee1 on May 10, 2010, 09:43:01 AM
-
So I know I've seen it before, I'm pretty sure I have even played around with it. But for the life if me I can't find or remember how to tell an actor how to use the avoid script. Anybody else remember how to do this?
-
I posted my own questions about this ages ago and never got an answer. How I wish we had members who knew SCI code backwards and forwards....
-
I may have figured it out, but I'm not positive because of the way Ilm wanting to use it. In the actors init, or whenever you start them walking, add in doAvoider() that seems to be the correct command anyway. Unfortunately I want to use it in conjunctio with follow and follows doit method, I think, is overriding it so it never actually gets a chance to avoid anything. It should work though in a moveto situation but alas thats not what I am doing. A sloppy workaround might be to add in a changestate where case 0 is a couple of cycles, case 1 moves to egos x y while avoiding and when it reaches x and y go to case 3 which just has a command to go to case 0 again. the obvious drawbacks of course would be if you changed directions the following character wouldn't update until it reached the last point so it might look funny. As for adding it to ego I think it would work fine to add it in when the room inits the ego.
-
I know this is an old question, but just do:
(send badguy:setAvoider(Avoid))
where badguy is an object of type Act, and of course you need the Avoid script which isn't in Brian's original template game.
-
I am not sure how much work it would be to create a new template game, but it seems that there are certain limitations with it. I would expect that QfG2 would have a more robust parser.
-
Still just won't quite work. Here is the code I am using to init my goat who is supposed to be following the ego. This first bit of code has some serious issues, as soon as the goat hits a white control line he immediately heads off towards 2:00 and never looks back, not even when he hits another white line and it also throws an OOPS error when attempting to leave the screen.
(goat:init()
setCycle(Walk)
setAvoider(Avoid)
setMotion(Follow gEgo 30)
posn(320 (send gEgo:y))
loop((send gEgo:loop))
)
So a couple of variations, this does not throw an oops error, but no avoiding takes place.
setAvoider(ctlWHITE)
And finally, we have this one. This time, there is avoiding taking place but we are back to the oops error when exiting the screen
setAvoider(Avoid ctlWHITE)
All three variations compile without error, just none of them work. If anyone could help me figure this out, I would appreciate it.
-
Return of the Black Cauldron? :). I'll play around with the avoid script this weekend. Can you elaborate on what you are trying to do? It looks like you have the goat following the ego but want the goat to get out of the way when it you move toward it?
-
I want the goat to try and unstick itself when it gets caught on the white control line of trees, rocks, and other obstacles while following the ego.
-
Is there a way to get the Avoid script to work without the Follow script? Here's what I have:
(doppleganger:init()
setCycle(Walk)
setAvoider(Avoid)
setMotion(MoveTo 20 202)
)
I set up a white control line in the actor's path, and it just stops when it hits it. In this context, the avoid script doesn't seem to do anything.
Was the avoid script designed specifically to only be used in conjunction with the follow motion?
-
This was one of the improvements with later versions of SCI. Vastly improved walk paths, which I assumed was partly because of improved control/interaction of things like control lines. The characters didn't get hung on winding paths.
-
The Avoid script looks incomplete. I'm seeing 'goto' calls commented out:
in the doit()
(send theMover:doit())
(if (== (send client:x) clientX)
(if (== (send client:y) clientY)
// goto code_0254 // unimplemented code here
)(else
(self:pickLoop(angle))
return (++nonBumps)
)
)(else
(self:pickLoop(angle))
return (++nonBumps)
)
and again here:
// Increment our position! Finally!
(self:incClientPos())
(if (self:canBeHere)
// If I can be here, then increment the number of nonbumps.
// and we're done (unless we are escaping)
(++nonBumps)
(= bumpTurn 0)
(if (escaping)
// goto code_037F; // unimplemented code here
)(else
return
)
)(else
// Uhoh... we can't be here.
(= lastBumped bumpTurn)
(= bumpTurn thisTurn)
(= nonBumps 0)
)
Although, why would the Avoid.sc script be included in the template game if it didn't work. Maybe we are just missing something.
-
Anyone implement the avoid script successfully in any of their games? I've checked all the available source code of the fan games here, none of them have used it.
BTW: Cloudee, I have successfully reproduced your 3 scenarios (and results) as you posted earlier in a single one-room game. Note that example 2 is not valid, you do need to specify 'Avoid' as the first argument - similar to a call to the setMotion class (e.g. Follow, MoveTo). I'm not sure about specifying a control color for the 2nd argument as you did here:
setAvoider(Avoid ctlWHITE)
The 2nd parameter of the Avoid script maps to the 'offScreenOK' parameter of the script, but I'm not sure what that parameter does (yet).
-
That's unfortunate too. As the version with avoid and the control color was the version that came the closest to working. There was at least some avoiding going on in that scenario.
-
I tried several different tests. What's strange is I can always have the actor avoid the first contact of the white control color but any subsequent contact with a white control line the actor ignores and just keeps on going off-screen.
Once I was able to get the actor to observe contact with a second white control line, but now I can't reproduce it.
-
Unfortunately it is imperative that I get some sort of path finding working in this project. To that end, it looks like I am going to have to write my own...
Not real sure that is something that I am up to. We'll see how it goes.
Right now, I have the goat actor all set up in a region script. So for now, I plan to build my pathfinding into that script which handles all of the goats code. I have done some preliminary tests to try and gather some useful information while I walk around with my goat in tow. I am using the avoid script's variables where I can to see what it is that they tell me. Some of them don't seem to tell me anything.
(local
theMover // not real sure what this gives me, doesn't seem useful by itself
moverX // based off of theMover.. seems to reflect the target x
moverY// base off of theMover... seems to reflect the target y
theStatus // tells me if goat can be where it is
theStatus2 // tells me if goat can be where ego is
currentCtl // the current control color the goat is on
angle // the angle between where the goat is and the ego
)
Then in the handleEvent method so I can see my values.
= theMover (goat:mover)
= moverX (send theMover:x)
= moverY (send theMover:y)
= theStatus (goat:canBeHere((goat:x) (goat:y)))
= theStatus2 (goat:canBeHere(moverX moverY))
FormatPrint("The Mover: %d,\nmoverX: %d y: %d\nGoatX: %d y: %d\ncanBeHere: %d\ncanBeThere: %d" theMover moverX moverY (goat:x) (goat:y) theStatus theStatus2)
= currentCtl (goat:onControl())
= angle (ClampAngle(GetAngle((goat:x) (goat:y) moverX moverY) 360))
FormatPrint("Control: %d\nStopped: %d\nAngle: %d" currentCtl (goat:isStopped) angle)
and at the end of the script, a clampAngle procedure, copied straight from avoid
(procedure (ClampAngle param1 param2)
(= param1 (- param1 (* param2 (/ param1 param2))))
(if (< param1 0)
return (+ param1 param2)
)
return (param1)
)
Some things I have noticed so far. For 1, if the goat is hung up and still trying to walk, isStopped returns FALSE. As long as the goat is trying to move, it is not stopped. I need to figure out a way to check all points between where the goat is and where ego is because both of those values for canBeHere return true which makes sense because I'm checking where they are and they are in good spots or the game wouldn't let them be there. So those values tell me nothing.
I am thinking that in the end, I will probably drop the use follow from this script, and instead try to determine a path to the ego. Then I will set up a doit method with a setMotion dPath that leads to the ego around obstacles.
What I think the logic needs to be...
1. Get ego Posn.
2. Get goat Posn.
3. Determine angle between Posns.
4. Check path along angle
5. If can be here all along path, setmotion.
... this is where I am still pondering.
either get posn of first false and guess different directions to try and get there
try going a different direction left then down or whatever until I find a way through
but basicly I want to find a path before I setMotion.
15. if ego posn change, go to 1.
-
What about getting the goat's location and if it has not changed by at least X amount after a given time, set isStopped to true. It would be interesting to see how Sierra did it in KQ1SCI.
-
I was thinking about how to address the simpler approach with the MoveTo motion. The seemingly difficult scenario that comes to mind is a winding path down a mountain, or the castle path in BC. You'd set the actor at the beginning of the path and the destination at the end of it. I'm thinking the actor would look like a pinball in a chute, bouncing back and forth all the way down.
Seems like we'd have to take the angle of incident of the control line w/regard to the motion of the actor into account when determining where to 're-aim' the actor before the next movement. E.g. if the motion of the actor was perpendicular to the control line when it was hit, you'd probably want to change the angle before the next movement quite drastically, perhaps 90 degrees. However if the actor hits the control line at a shallow angle, where the actor is nearly parallel to the control line you'd want to change the angle less drastically, maybe just a few degrees.
It'll be interesting to see what you come up with.
-
Unfortunately, I am already stuck and I'm not real sure why.
I started from scratch, with an actor and an ego. I wrote a rather generic little bit of code that does an alright job of following the actor. I then threw up a control line and have been trying to get it to recognise and tell me that it has hit a boundry. It hasn't.
Room700
/************************************************/
(include "sci.sh")(include "game.sh") (script 700)
/************************************************/
(use "Controls")(use "Cycle")(use "Feature")(use "Game")(use "Main")(use "Obj")
/************************************************/
(local
targetX
targetY
currentX
currentY
recentX
recentY
currentDistance
currentDistanceX
currentDistanceY
theStatus
theStatus2
currentCtl
attempt = 0
sendActor = FALSE // actor walking
stealControl = FALSE // take control from the main doit loop
)
//***********************************************
(instance public pathfinding of Rgn
(properties)
(method (init)
(super:init())
(self:setScript(pathScript))
(thisActor:init()setCycle(Walk))
)// end method
)// end instance
//***************************************************
(instance thisActor of Act(properties x 10 y 100 view 1 loop 0 cel 0))
//***************************************************
(instance pathScript of Script
(properties)
(method (doit)
(super:doit())
(if(sendActor) // actor is walking
// step 1. get actors position...
//*******************************
= currentX (thisActor:x)
= currentY (thisActor:y)
// step 2. get ego's position...
//*******************************
= targetX (send gEgo:x)
= targetY (send gEgo:y)
// step 3. determine distance...
//********************************
= currentDistanceX (- currentX targetX)
= currentDistanceY (- currentY targetY)
(if(< currentDistanceX 0) // should be an absolute operator, but I don't know it.
= currentDistanceX (* currentDistanceX -1)
)
(if(< currentDistanceY 0)
= currentDistanceY (* currentDistanceY -1)
)
// step 4. determine if hungup
//*******************************
(if(== (thisActor:isStopped) 0) // should be moving.
(if((== recentX currentX) and (== recentY currentY))
Print("stuck")
= stealControl TRUE
(if(== attempt 3)
= attempt 0
)
(else
++attempt
)
)
(else
= recentX currentX
= recentY currentY
)
)
// step 10. make a path...
//********************************
// Now that we have some variables, lets send our actor walking...
(if((> currentDistanceX 30) or (> currentDistanceY 20))
(if(not(stealControl))
(thisActor:setMotion(MoveTo targetX targetY))
)
(else
// Try an alternative path here
(switch(attempt)
(case 0 (thisActor:setMotion(MoveTo currentX (- currentY 30) pathScript)))
(case 1 (thisActor:setMotion(MoveTo currentX (+ currentY 30) pathScript)))
(case 2 (thisActor:setMotion(MoveTo (- currentX 30) currentY pathScript)))
(case 3 (thisActor:setMotion(MoveTo (+ currentX 30) currentY pathScript)))
)
)
)
(else
(thisActor:setMotion(NULL))
)
)// end sendActor TRUE
)// end method
(method (handleEvent pEvent)
(super:handleEvent(pEvent))
(if(Said('hi'))
= sendActor TRUE
= targetX (send gEgo:x)
= targetY (send gEgo:y)
= theStatus (thisActor:canBeHere((thisActor:x) (thisActor:y)))
= theStatus2 (thisActor:canBeHere(targetX targetY))
FormatPrint("targetX: %d y: %d\nthisActorX: %d y: %d\ncanBeHere: %d\ncanBeThere: %d" targetX targetY (thisActor:x) (thisActor:y) theStatus theStatus2)
= currentCtl (thisActor:onControl())
FormatPrint("Control: %d\nStopped: %d" currentCtl (thisActor:isStopped))
)
)// end method
(method (changeState newState)
(= state newState)
(switch (newState)
(default
// Handle state changes
= stealControl FALSE
)
)
)
)
Then in the room1 script simply add the call to use the region
(self:setRegions(700)) // actor
Now all you need to test it is a view saved as 1.
Like I said, the bit that follows the ego around works, and to make it happen you just type in "hi". Also to view the variables set up, just retype hi. My initial thoughts of using dpath in conjunction with the doit method didn't quite work out like I had planned. I'm trying to start out simply and work my way up to something.
This part here is never returning TRUE even though I am pretty sure that it should when the actor gets stuck. My plan to handle the problem won't work in the long run, this is just a starting point to figure out where in the code to do stuff.
(if((== recentX currentX) and (== recentY currentY))
-
That last bit is something along the lines of what I was suggesting, but what if the hang allows some movement. Checking for an exact match of X and Y might not reveal that the character is hung if it has moved by even a couple of pixels. Seems like you would have to test against a range.
-
Hey, for the absolute value just wrap the value with the Abs() kernel function call.
Abs(currentDistanceX)
I've implemented your region and have it working as you've described. The actor will follow the ego and the actor does get stuck. Moving the ego around the actor unsticks the actor, so at least that works. I'll play around with this and see if I can make any progress.
EDIT: Cloudee, change this line here, this will cause the actor to unstick itself:
// step 4. determine if hungup
//*******************************
(if(== (thisActor:isStopped) 0) // should be moving. <------ change the zero to one.
The 'stuck' message fires, the actor gets unstuck and heads off to edge of the screen, but at least it doesn't get stuck!
-
But that line checks against a real value. If you type hi while the actor is moving, you will see that it returns 0. Hit hi again while he is stopped, but not because he is stuck, and you will see that it returns 1. Try it again while he is stuck but should be moving and you'll see the 0 again. So in the case of the 1, you are sending him off and running when he shouldn't be moving at all... Remember the first time you hit hi, he is stopped, he doesn't start until after the print statement....
That is pretty cool though that he does something. Just not quite sure why he is doing what he's doing lol with that value changed to 1
Collector, the x step of a character varies, but is usually pretty small. A single valid step may only be a few pixels. Since I am checking every cycle, I want to know when he comes to a dead stop. Which clearly happens, by checking the hi values repeatedly when he is stuck, the current = recent check should come up positive.
Oh yeah Gumby thanks for the absolute operator, I knew there was one out there just couldn't remember what it was.
EDIT:
Wow, that was really ugly...
So I know my boundary is a vertical line. At this point I am just trying some options to get around it. Here is what I did.
First I changed section 4, including the line that Gumby pointed out
// step 4. determine if hungup
//*******************************
(if(== (thisActor:isStopped) 1) // should be moving.
(if((== recentX currentX) and (== recentY currentY))
// Print("stuck")
= stealControl TRUE
= attempt Random(0 3)
)
(else
= recentX currentX
= recentY currentY
)
)
Oh yeah, I also trimmed down section 3 to what it should have been originally.
// step 3. determine distance...
//********************************
= currentDistanceX Abs(- currentX targetX)
= currentDistanceY Abs(- currentY targetY)
And I changed the values in section 10, like I said I know how he's stuck and which side I am sticking him on so while these won't get us anywhere near production, it is at least a good test with expectable results. Regardless though, this sort of worked but not really at all.
// step 10. make a path...
//********************************
// Now that we have some variables, lets send our actor walking...
(if((> currentDistanceX 30) or (> currentDistanceY 20))
(if(not(stealControl))
(thisActor:setMotion(MoveTo targetX targetY))
)
(else
// Try an alternative path here
(switch(attempt)
(case 0 (thisActor:setMotion(MoveTo (- currentX 2) (- currentY 30)(pathScript:changeState(0)))))
(case 1 (thisActor:setMotion(MoveTo (- currentX 2) (- currentY 60) (pathScript:changeState(0)))))
(case 2 (thisActor:setMotion(MoveTo (- currentX 30) currentY (pathScript:changeState(0)))))
(case 3 (thisActor:setMotion(MoveTo (- currentX 60) currentY (pathScript:changeState(0)))))
)
)
)
(else
(thisActor:setMotion(NULL))
)
And finally, I changed the default line in the changestate method so that it was the case 0 that the moveto in the last section was looking for in order to trigger the following bit of code again.
(method (changeState newState)
(= state newState)
(switch (newState)
(case 0 = stealControl FALSE)
)
)// end method
The good news, suprisingly the actor made it around the solid line. The bad news, he didn't do it in any sort of fashion that he should have. It was ugly and not at all recognisable by the moveTo statements. Also, with the isStopped value changed, when he is successful and made it within the distance to ego the stuck message still fired. I am still positive that check should be set to 0
EDIT #2
And actually, even though my attempt to get him around the boundary was to subtract from his x position, he got around the wall just as well going from east to west. I certainly don't think that should have been the case. This is just plain wierd... but he got around the wall from both sides. I guess I need to make a box or a harder shape and see what happens.
-
Alright Phil, since you are back here again... I figured I would resurrect this thread. The avoid script really doesn't seem functional... Was wondering if you might want to run the sq3 avoid script through the decompiler again just in case some of the commented out assembly code that is still there might be better translated.
Currently, using this line to init an actor... when the actor hits a white control line, it takes off in the opposite direction and never really looks back.
(testViewAvoid:init()setCycle(Walk)setMotion(Follow gEgo 15)setAvoider(Avoid))
-
I noticed the Avoid script is in SQ4 too. I don't know how different it is, having not compared, but it might be worth taking a look at too.
-
Here's the decompiled SQ3 one (note that the script number is different, so you'll need to change that).
I'm not sure how well it will work, since it needs proper support for embedded if statements and I'm not sure if the old SCI Companion supported that properly. At the very least you'll get lots of warnings.
I was able to use the Avoid script somewhat successfully in Cascade Quest. But I do recall in rare circumstances it would get infinitely stuck.
-
Holy Crap, I got it to work...
All I had to do was replace the init method of the avoid script.
What it was
(method (init theClient theOffScreenOk)
(if (>= paramTotal 1)
(= client theClient)
(if (>= paramTotal 2)
(= offScreenOK theOffScreenOk)
)
(= heading (send client:heading))
)
(= counter 0)
(= nonBumps 10)
(= escaping 0)
)
and what it should be
(method (init theClient theOffScreenOK)
(if (>= paramTotal 1)
= client theClient
)
(if (>= paramTotal 2)
= offScreenOK theOffScreenOK
)
= heading (send client:heading)
= counter 0
= nonBumps 10
= escaping 0
)
and with that, I used this code to get it all going with the actor...
(scientist:setCycle(Walk)setMotion(Follow gEgo 20)setAvoider(Avoid 1))
actually I may not have needed to change the init method afterall, but it definately apperas as though you need to send the second parameter across. With the 1 removed or set to 0 I get the same reaction of the actor hitting a control line and promptly walking in the opposite direction.
... Ah Crap, when trying to leave the room I get an oops error
-
Does it work properly now? Like, does it still get stuck?
Also, what's the difference between the two code snippets? They look functionally identical except that the second one will crash if no parameters are passed to Avoid (since client will be null, it will send heading to a null object).
-
I never had the issue with it getting stuck. The actor would touch a control line and the head in the exact opposite direction without ever looking back again. At least now, the actor bounces around a bit instead which is a vast improvement.
And yeah, the two snippets are pretty much the same except that heading was pulled out regardless of the parameter settings. It turns out (I assume) that the real difference this time was sending 1 ...setAvoider(Avoid 1)
Unfortunately now I can't leave the room without getting the oops error. So things are still looking bad on my end of things.
Also sending a 0 instead of the 1 reproduces the original failing avoid scenario
-
Unfortunately now I can't leave the room without getting the oops error. So things are still looking bad on my end of things.
sciv -d will give you more useful debug messages instead of an oops (and, I believe, an opportunity to inspect the send stack).
-
How do you pass command line parameters to an exe in DOSBox? For the life of me I can't figure it out. You'd think it would be a common scenario, but the documentation mentions nothing.
-
Ok, but I really don't know what it is that this tells me... I assume that it has something to do with avoid being a class of the obj... but yeah
Not an object: $e226
Avoid
mul
acc:e226 sp:1868 pp:1860
Phil, if you used the dosboxsetup thing, then there will be dosbox.conf file in your games root folder. In the autoexec bit, add the bit to the command line
[autoexec]
cls
@ECHO OFF
mount c .
c:
cd \
SCIV.EXE -d
exit
-
Ok, but I really don't know what it is that this tells me... I assume that it has something to do with avoid being a class of the obj... but yeah
Not an object: $e226
Avoid
mul
acc:e226 sp:1868 pp:1860
You left out the send stack :) but I've just had a look at the earlier posts here. So you are using this in conjunction with a region, and setting offScreenOK...
that might indicate that either the region, the avoider itself or an actor is being disposed ahead of time. You should be able to inspect the object at $e226 while still in the room and see what it is.
-
Cool, thanks for the dosbox tip, that works.
I can repro this even with the template game Avoider script. It's crashing because the object it's trying to send to has been disposed. To me, the code in Act::setAvoider looks wrong in the template game. I think it should set avoider to NULL after disposing it.
The send stack is:
(aThing setAvoider:)
(aThing delete:)
(cast eachElementDo:)
(Game newRoom:)
etc....
-
In Cascade Quest, an old game I was working on that used avoiders, setAvoider looks like this:
(method (setAvoider theAvoider sendParams)
(if(avoider)
(send avoider:dispose())
)
(if(IsObject(theAvoider))
(if(& (send theAvoider:{-info-}) $8000)
= avoider (send theAvoider:new())
)(else
= avoider theAvoider
)
)(else
(= avoider NULL)
)
(if(avoider)
(send avoider:
init(self)
rest sendParams
)
)
)
Note the assignment to NULL if theAvoider is not an object.
(Note: the decompiled version of setAvoider looks correct too)
-
;)
I didn't set mine to NULL, but I did manage to make it out of the room again by adding in an else statement in the same area you did.
Looking at sq4 picview script, I noticed that there was an and thrown in there and the two lines appeared as one. Where as in the template, the same line was broken up with two if statements. But only the second one had an else following... which meant that if it passed the first if and failed the second then something was falling through...
I stuck in the original response as demonstrated by the decompile
(method (setAvoider theAvoider sendParams)
(if (avoider)
(send avoider:dispose())
)
(if (IsObject(theAvoider))
(if(& (send theAvoider:{-info-}) $8000)
= avoider (send theAvoider:new())
)
(else
= avoider theAvoider
)
)
(else
= avoider theAvoider
)
(if (avoider)
(send avoider:init(self rest sendParams))
)
)
-
Looking at sq4 picview script, I noticed that there was an and thrown in there and the two lines appeared as one. Where as in the template, the same line was broken up with two if statements. But only the second one had an else following... which meant that if it passed the first if and failed the second then something was falling through...
Yeah, looks like Brian "manually decompiled" it incorrectly. Not surprising, it's very tedious and error-prone for a human to do, and that bit of code was never tested since the Avoider script wasn't part of the original template game.
So, are things working better now with the template game fix, and the decompiled Avoider script?
-
Holy crap... Looking at the first post in this thread, it started 5 years ago yesterday.
The good news is, today the problem is solved. Now it's time to go back and retrofit some code.
I had faked my own cheap avoider by outlining the white control lines with some navy ones and then checking for & onControl navy. If true it would switch the motion to wander for a few cycles, and then switch back to follow. It definitely wasn't pretty... and now I can get rid of it. 8)
I'll have to get back to you on how well everything works, it looks like in your original avoider script you provided, there is the offscreen procedure that got added in from somewhere as it isn't in the sq3 avoid script. I haven't found it yet in the other decompiles you have provided but I will be looking for it... especially since I am sending true for ok to be off screen.
I am trying to get as much functionality as possible in the current templates so that I can stick up a new version of each. The goal is to get them as close to sci1.1 as possible so that a lot of the same code can be used in almost any version.
Unfortunately I am really struggling to decipher the iconBar but anyway, I am so glad this avoid business is back on track.
-
So much progress and activity lately. :) So nice to see.
-
Apparently Phil knows how to stir things up a bit
You know something is going on when Lars comes out of lurker mode and starts getting his hands dirty
-
So I just got to thinking and I thinks this would work.
Let's say I have a little invisible actor. Whenever I click to send the ego walking... instead I position my little invisible actor wherever it is that I clicked.
Now when my room was inited let's say I told my ego to follow that little invisible actor and of course set the avoider.
Theoretically don't I now have an ego with some path finding abilities... even if he is a tad soft in the head.
As long as I white out everywhere an actor can't be anyone see any reason why this wouldn't work?
-
Ahhh.....I remember trying to use Avoid in the past to implement pathfinding but was unsuccessful. Never thought of this method, though.
-
So I just got to thinking and I thinks this would work.
Let's say I have a little invisible actor. Whenever I click to send the ego walking... instead I position my little invisible actor wherever it is that I clicked.
Now when my room was inited let's say I told my ego to follow that little invisible actor and of course set the avoider.
Theoretically don't I now have an ego with some path finding abilities... even if he is a tad soft in the head.
As long as I white out everywhere an actor can't be anyone see any reason why this wouldn't work?
I'm not sure what you're getting at... wouldn't the ego just walk toward the invisible actor? How is that any different than just telling the ego to MoveTo the position you clicked?
I think the bumping around that the Avoider does when it runs into obstacles might become distracting... like you don't have control over your character.
I'm not yet sure how the SCI1.1 stuff works... I imagine they send the actors along fixed prescribed paths?
You could implement an A* pathfinding algorithm if you divided the walkable area into cells, but I think that would be a lot of work.
-
I'm not yet sure how the SCI1.1 stuff works... I imagine they send the actors along fixed prescribed paths?
Polygons and AvoidPath (ok, it's wrapped in classes so you can just (foo setMotion: PolyPath), but still)?
-
You could implement an A* pathfinding algorithm if you divided the walkable area into cells, but I think that would be a lot of work.
Working on this now. I'm taking an approach similar to sciAudio, where the processing is external to the SCI engine. Pass in the current coordinates of the actor, the X/Y coordinate of the destination, which control colors to observe and an array of coordinates are returned which can be fed into DPath. It'll have to evaluate the room pic and find the corresponding control lines (just lines at this point).
Already have the pathfinding part complete, I grabbed an implementation from CodeProject (http://www.codeproject.com/Articles/118015/Fast-A-Star-D-Implementation-for-C). All that remains is to trudge through the pic resource identifying all the control lines (just lines at this point) and create a bitmap which is used as input for the pathfinding. Then just connect it up to the SCI engine utilizing file reads/writes.
-
Dear lord that's horrifying :D
-
Making progress on this. Building a list of control lines from a room pic is done. Doesn't make a difference if it's in a resource archive or 'patch' file.
EDIT: Pathfinding is wired in, tested and working. Wicked fast. Now all that is left is to hook it into SCI.
-
Haha, that's pretty out there!
(Though wonder if there's a Sierra interpreter version that includes both AvoidPath and parser functionality)
-
(Though wonder if there's a Sierra interpreter version that includes both AvoidPath and parser functionality)
ScummVM, if you muddle it up a bit.
-
Pathfinding test, see attached image. The black lines are the control lines that the actor cannot cross, the red is the path taken by the actor. I'm very pleased so far with what I'm seeing.
-
Well, I bombed out on this. Everything was going well until I put it into practice. The actor kept getting stuck on control lines, so tried to pad the lines with extra pixels. Unfortunately it required way too much padding to make it practical.
Oh well, time to move on to something more rewarding. Chalk this one up to a learning experience.
-
That's too bad. But the fun is in the experience. :)