Author Topic: Scene Repair  (Read 5229 times)

  • Hero Member
  • *****
  • Posts: 509
    • View Profile
Re: Scene Repair
« Reply #60 on: December 30, 2019, 02:32:55 pm »
I’ve changed sprite 267 and added the sprite with the green speed indicator. I think anything else after that is just script changes.

  • Administrator
  • Sr. Member
  • *****
  • Posts: 407
    • View Profile
Re: Scene Repair
« Reply #61 on: January 07, 2020, 12:18:10 am »
That is true mess. Awful resized bitmap backpad for controller and Crow-style inefficient implementation.
Please do not waste your time on this, there is much more sophisticated way to do that using simple copy-paste-edit script.

For start lets learn how to draw rounded rectangle pad with pink line and how to place text on that.
Let's assume we have a SWF file with a loading screen in frame 1 and scene in frame 2. Let's assume there is no controller at all yet. So have a key script (action?) for frame 2, where is already stop(); statement to stop the file in that last frame.
Add following code to that script:

// first create a function to draw rounded rectangle back pad
function drawRoundedRectangle(target_mc:MovieClip, boxWidth:Number, boxHeight:Number, cornerRadius:Number):Void
{  // Note: when using FFDec, omit parameter types as FFDec can't compile parameter types and flash ignores types anyway
  with (target_mc)
  {
    beginFill(0x000000, 100); // black fill, full aplha
    lineStyle(5, 0xff00ff, 100); // line 5 points wide, some pink color (RGB 0xff00ff), 100% alpha
    moveTo(cornerRadius, 0);
    lineTo(boxWidth - cornerRadius, 0);
    curveTo(boxWidth, 0, boxWidth, cornerRadius);
    lineTo(boxWidth, cornerRadius);
    lineTo(boxWidth, boxHeight - cornerRadius);
    curveTo(boxWidth, boxHeight, boxWidth - cornerRadius, boxHeight);
    lineTo(boxWidth - cornerRadius, boxHeight);
    lineTo(cornerRadius, boxHeight);
    curveTo(0, boxHeight, 0, boxHeight - cornerRadius);
    lineTo(0, boxHeight - cornerRadius);
    lineTo(0, cornerRadius);
    curveTo(0, 0, cornerRadius, 0);
    lineTo(cornerRadius, 0);
    endFill();
  }
}
// Now Lets assume we have a main timeline frame with a scene object and no controller object yet.
// So lets create a controller object atop of all others.
// MovieClip type object is a rendered (displayed) object,
// while a basic "Object" type is just a data structure (not displayed)
// Unlike any other object it can't be creater/removed by new/delete statements
// but has special methods to put it on stage or remove from.
this.createEmptyMovieClip("controller", this.getNextHighestDepth()); // creates a MovieClip type object in highest free layer named "controller"
// move this object to desired coordinates
controller._x = 40;
controller._y = 40; // location coordinates from left top corner in default resolution pixels
// now draw a backdrop. See function definition on parameters meaning
drawRoundedRectangle(controller, 200, 50, 5);
// Now create a text label "SPEED" in that rectangle using TextField method
//createTextField(instanceName:String, depth:Number, x:Number, y:Number, width:Number, height:Number)
controller.createTextField("label", controller.getNextHighestDepth(), 0, 5, 75, 25);
// set TextField object named "label" actual text
controller.label.text = "SPEED";
// set a text format. Need a special object holding that data for TextField
var textformatdata:TextFormat = new TextFormat();
textformatdata.size = 18;
textformatdata.bold = true;
textformatdata.font = "Arial Black"; // System fonts are used, not fonts packed in SWF file.
textformatdata.color = 0xffffff; // white RGB code
textformatdata.leftMargin = 5;
// apply format on our label using it's setTextFormat() method
controller.label.setTextFormat(textformatdata);

You can create "Back" od "Done" button object the same way: just smaller size parameter, different _x & _y coordinates and different text value.


Next time I'll post how to create buttons in that object, how to make them change white-green color and do desired action.
« Last Edit: January 09, 2020, 11:30:54 pm by Tabby »

  • Hero Member
  • *****
  • Posts: 509
    • View Profile
Re: Scene Repair
« Reply #62 on: January 07, 2020, 03:15:16 pm »
For the green indicators you could just use sprites. It’s a little easier

  • Administrator
  • Sr. Member
  • *****
  • Posts: 407
    • View Profile
Re: Scene Repair
« Reply #63 on: January 09, 2020, 11:37:23 pm »
// Now how to create a button. Because we will have multiple of these, create a function to generate buttons:
function createDummyButton(target_mc:MovieClip, name:String, text:String, x:Number, y:Number, width:Number, height:Number, key:String):Void
{
  // 1. create an object holding a button structures
  target_mc.createEmptyMovieClip(name, target_mc.getNextHighestDepth());
  target_mc[name]._x = x; // set coordinates; indexing object by the name in function parameter
  target_mc[name]._y = y;
  // 2. create a clickable rectangle, otherwise button would work only when clicked text exactly, not a hole in a "O" for example.
  // Make is a subobject so it's visibility can be controlled independently from text.
  target_mc[name].createEmptyMovieClip("pad", 1); // using layer 1 (deepest for pad)
  // draw an invisible (alpha 0) white rectangle in that object
  with (target_mc[name].pad)
  {
    beginFill(0xffffff, 100); // white fill
    lineTo(width,0);
    lineTo(width,height);
    lineTo(0,height);
    lineTo(0,0);
    endFill();
    _alpha = 0; // invisible by default
  }
  // 3. create a button text object named "label"
  target_mc[name].createTextField("label", 2, 0, 0, width, height); // using layer 2 (just above pad pad)
  target_mc[name].label.text = text; // set actual text
  // set a text format. Need a special object holding that data for TextField
  var textformatdata:TextFormat = new TextFormat();
  textformatdata.size = 18;
  textformatdata.bold = true;
  textformatdata.font = "Arial Black"; // System fonts are used, not fonts packed in SWF file.
  textformatdata.color = 0xffffff; // white RGB code
  textformatdata.leftMargin = 2;
  // apply format on our label using it's setTextFormat() method
  target_mc[name].label.setTextFormat(textformatdata);
  // 4. make button pad rectangle visible when mouse is over
  target_mc[name].onRollOver = function()
  {
    this.pad._alpha = 30; // make it 70% transparent
  };
  target_mc[name].onRollOut = function()
  {
    this.pad._alpha = 0;  // make it invisible when mouse is out
  };
  // 5. create helper methods to change button text color
  target_mc[name].turnGreen = function()
  {
    var textformatdata:TextFormat = new TextFormat();
    textformatdata.color = 0x00ff00; // green
    this.label.setTextFormat(textformatdata); // apply to button text text
  };
  target_mc[name].turnWhite = function()
  {
    var textformatdata:TextFormat = new TextFormat();
    textformatdata.color = 0xffffff; // white
    this.label.setTextFormat(textformatdata);
  };
  // 6. make the button selectable by Tab key & Enter
  target_mc[name].focusEnabled = true;
  target_mc[name].tabEnabled = true;
  // 7. if key parameter has proper length (one character), make it keyboard active
  if(key.length == 1)
  {
    target_mc[name].keycode = key.charCodeAt(0); // Store key parameter first (and the only) character Ascii code
    target_mc[name].onKeyDown = function() // create a function for processing keyboard events
    {
      if(Key.getAscii() == this.keycode) // pressed keyboard code match button stored key code
      {
        this.onRelease();  // on matching key hit call the same function as for mouse click, which is not defined yet.
      }
    };
    // register this button object among system keyboard listener object (Key is static object in Flash player)
    Key.addListener(target_mc[name]);
  }
  // 5. leave on press/release script for later as it is button specific
}


// Now use that function for the first two buttons, for speed 1 at coordinates 80,5 (just after "SPEED" text)
createDummyButton(controller,"button1","1",80,5,20,25,"1");
controller.button1.onRelease = function() // define what that button is suposed to do:
{
   this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("a"); // scene control call
   this.turnGreen();                 // turn button green
   this._parent.button2.turnWhite(); // turn the other button (not defined yet) white
};
// The second button on coordinates just 20 pcx right of the first button
createDummyButton(controller,"button2","2",100,5,20,25,"2");
controller.button2.onRelease = function()
{
   this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("b");
   this.turnGreen();
   this._parent.button1.turnWhite(); // turn the another button white
};
//Now we can copy-paste-modify to create as many buttons as we want easily. No need to create any flash structure (sprites etc), all is created by this script from nothing.

Note on code 1:
Unlike in C++, method (object associated function) in Flash AS2 doesn't have focus of the object which it belongs to but a random focus of a script in which the function body is defined. So it is not really a method, but a generic function with unlisted "this" pointer to the object which it is declared part of. So you have to use "this" pointer to access any data declared outside the function.
Note on code 2:
There is a bug in Flash player that ruins "this" pointer inside "with(){}" statement. So never use "this" pointer in "with" statement. It also ruins "this" pointer in every method/function called inside "with" statement. So use "with" statement cautiously and only for simple things.
Note on code 3:
In AS2/Flash we can use variables and call object methods not defined yet (neither declared as virtual functions) because in Flash (and also Java and similar languages) these things are not compiled into memory offsets but all data are searched by names during code execution. So entire Flash is a tree of associative arrays where data are searched by names in hash tables or something. I'm not a programmer, just average guy, so I find it freak and computationally inefficient.
Note on code 4:
Types in AS2 are most likely used only for some formal check by Adobe tool compiler. Types are thrown away in compilation. FFDec can't even compile code with types declared. Flash player simply ignores type, so it asserts string or pointer to a variable that was a originally number type. Variable type is changed by value assertion. So if you add two variables, the result may be a number or a string depending what was loaded to variables last time. It's good idea to use AS2 special functions line "isNaN()" to verify that input to math operation is actually a number.
« Last Edit: January 10, 2020, 12:27:39 am by Tabby »

  • Administrator
  • Sr. Member
  • *****
  • Posts: 407
    • View Profile
Re: Scene Repair
« Reply #64 on: January 11, 2020, 11:14:00 pm »
Finally, how to make a controller using functions
drawRoundedRectangle(target_mc:MovieClip, boxWidth:Number, boxHeight:Number, cornerRadius:Number)
and
createDummyButton(target_mc:MovieClip, name:String, text:String, x:Number, y:Number, width:Number, height:Number, key:String)
created in previous posts.

// first of all, create a Back button:
// create a standalone rounded rectangle named "ctrlback" for that on the bottom of the stage
this.createEmptyMovieClip("ctrlback",this.getNextHighestDepth());
ctrlback._x = 10;
ctrlback._y = 325;
drawRoundedRectangle(ctrlback,63,30,5);
// create a back button inside that
createDummyButton(ctrlback,"buttonback","Back",2,0,57,25,"");
ctrlback.buttonback.onRelease = function()
{
   _root.LVL.prevFrame();
   _root.npc_status = "back";
};

// Lets create main controller object atop of all others.
this.createEmptyMovieClip("controller", this.getNextHighestDepth()); // creates a MovieClip type object in highest free layer named "controller"
// move this object to desired coordinates
controller._x = 10;
controller._y = 40; // location coordinates from left top corner in default resolution pixels
// now draw a backdrop. See function definition on parameters meaning
drawRoundedRectangle(controller, 200, 50, 5);
// Now create a text label "SPEED" in that rectangle using TextField method
//createTextField(instanceName:String, depth:Number, x:Number, y:Number, width:Number, height:Number)
controller.createTextField("label", controller.getNextHighestDepth(), 0, 5, 75, 25);
// set TextField object named "label" actual text
controller.label.text = "SPEED";
// set a text format. Need a special object holding that data for TextField
var textformatdata:TextFormat = new TextFormat();
textformatdata.size = 18;
textformatdata.bold = false;
textformatdata.font = "Arial Black"; // System fonts are used, not fonts packed in SWF file.
textformatdata.color = 0xffffff; // white RGB code
textformatdata.leftMargin = 5;
// apply format on our label using it's setTextFormat() method
controller.label.setTextFormat(textformatdata);

// We have a main animation in object focus.camera.area.char.kendra which have
// multiple parts, each starting in a frame with a label:
// "in" scene start, "a" speed 1, "b" to "e" speeds 2 to 5, "knot" knotting,
// "a_knot", "b_knot" ... "e_knot" knotted version of speeds 1 to 5
// "x1" climax, "x2" knotted climax

// Now create 5 speed buttons in the main "controller" rectangle:
// for speed 1 at coordinates x 90, y 5 (just after "SPEED" text)
createDummyButton(controller,"button1","1",90,5,20,25,"1");
// define button action
controller.button1.onRelease = function()
{
   this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("a");
   this.turnGreen(); // turn this button green, turn other speed buttons white
   this._parent.button2.turnWhite();
   this._parent.button3.turnWhite();
   this._parent.button4.turnWhite();
   this._parent.button5.turnWhite();
};
// but that would not work for knotted part, so create a varibale to hold that
// status and decide button action based on that
controller.knotted = false;
controller.button1.onRelease = function()
{
   if (_parent.knotted)
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("a_knot");
   }
   else
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("a");
   }
   this.turnGreen(); // turn this button green, turn other speed buttons white
   this._parent.button2.turnWhite();
   this._parent.button3.turnWhite();
   this._parent.button4.turnWhite();
   this._parent.button5.turnWhite();
};

// the same with other speed buttons
createDummyButton(controller,"button2","2",110,5,20,25,"2");
controller.button2.onRelease = function()
{
   if (_parent.knotted)
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("b_knot");
   }
   else
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("b");
   }
   this.turnGreen();
   this._parent.button1.turnWhite();
   this._parent.button3.turnWhite();
   this._parent.button4.turnWhite();
   this._parent.button5.turnWhite();
};
createDummyButton(controller,"button3","3",130,5,20,25,"3");
controller.button3.onRelease = function()
{
   if (_parent.knotted)
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("c_knot");
   }
   else
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("c");
   }
   this.turnGreen();
   this._parent.button1.turnWhite();
   this._parent.button2.turnWhite();
   this._parent.button4.turnWhite();
   this._parent.button5.turnWhite();
};
createDummyButton(controller,"button4","4",150,5,20,25,"4");
controller.button4.onRelease = function()
{
   if (_parent.knotted)
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("d_knot");
   }
   else
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("d");
   }
   this.turnGreen();
   this._parent.button1.turnWhite();
   this._parent.button2.turnWhite();
   this._parent.button3.turnWhite();
   this._parent.button5.turnWhite();
};
createDummyButton(controller,"button5","5",170,5,20,25,"5");
controller.button5.onRelease = function()
{
   if (_parent.knotted)
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("e_knot");
   }
   else
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("e");
   }
   this.turnGreen();
   this._parent.button1.turnWhite();
   this._parent.button2.turnWhite();
   this._parent.button3.turnWhite();
   this._parent.button4.turnWhite();
};
// now the climax button
createDummyButton(controller,"buttonclimax","Climax",5,30,75,25,"x");
controller.buttonclimax.onRelease = function()
{
   // Play climax animation:
   if (_parent.knotted)
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("x2");
   }
   else
   {
     this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("x1");
   }
   // Replace Back button with Done button:
   // Delete Back button in ctrlback rectangle first
   this._parent._parent.ctrlback.buttonback.removeMovieClip();
   // Create Done button in place of that
   createDummyButton(this._parent._parent.ctrlback,"buttondone","Done",2,0,57,25,"");
   // define button action
   this._parent._parent.ctrlback.buttondone.onRelease = function()
   {
      _root.LVL.prevFrame();
      _root.npc_status = "done";
   };
   // and finally remove entire main "controller" object with speed buttons
   this._parent.removeMovieClip();
};
// create knot button only if player is canine
if(_root.genus == "canine")
{
   createDummyButton(controller,"buttonknot","Knot",80,30,55,25,"k");
   controller.buttonknot.onRelease = function()
   {
      this._parent._parent.focus.camera.area.char.kendra.gotoAndPlay("knot");
      this.turnGreen();
      this._parent.button1.turnWhite();
      this._parent.button2.turnWhite();
      this._parent.button3.turnWhite();
      this._parent.button4.turnWhite();
      this._parent.button5.turnWhite();
      // set knotted state variable so speed buttons play knotted variation
      _parent.knotted = true;
      // delete button actions so button does nothing when knotted already
      this.onRelease = function()
      {
      };
   };
}

// Now create a zoom control there are 2 approaches to that
// Make it +- zoom:
// Create button without rectangle at bottom right of the stage
createDummyButton(this,"buttonzoomin","+",500,330,20,25,"+");
buttonzoomin.onRelease = function()
{
   // choose some object in maing animation hierarchy. It' heavily nested,
   // easiest is a one without scale and offset matrix so default position is 0, 0, 100% scale
   // now on each click increase scale and move it so desired part (pus*y) is in the center
   this._parent.focus.camera.area._xscale = this._parent.focus.camera.area._xscale + 10;
   this._parent.focus.camera.area._yscale = this._parent.focus.camera.area._yscale + 10;
   this._parent.focus.camera.area._x = this._parent.focus.camera.area._x + 20;
   this._parent.focus.camera.area._y = this._parent.focus.camera.area._y + 10;
};
createDummyButton(this,"buttonzoomout","-",530,330,20,25,"-");
buttonzoomout.onRelease = function()
{
   // the opposite for zoom out. There may be some condition to limit zoom out.
   this._parent.focus.camera.area._xscale = this._parent.focus.camera.area._xscale - 10;
   this._parent.focus.camera.area._yscale = this._parent.focus.camera.area._yscale - 10;
   this._parent.focus.camera.area._x = this._parent.focus.camera.area._x - 20;
   this._parent.focus.camera.area._y = this._parent.focus.camera.area._y - 10;
};
// Alternative approach: camera with fixed view points:
// Create it as a button with toggling function of switching two view points
createDummyButton(controller,"buttonzoom","Zoom",132,30,60,25,"z");
// declare variable holding camera point in that button object
controller.buttonzoom.camera = 1;
controller.buttonzoom.onRelease = function()
{
   // if it's the first camera point, move to the second
   if(this.camera == 1)
   {
      this.turnGreen();
      this._parent._parent.focus.camera.area._xscale = 160;
      this._parent._parent.focus.camera.area._yscale = 160;
      this._parent._parent.focus.camera.area._x = 120;
      this._parent._parent.focus.camera.area._y = 60;
      this.camera = 2;
   }
   // if it's not the first camera point, move back to the first
   else
   {
      this.turnWhite();
      this._parent._parent.focus.camera.area._xscale = 100;
      this._parent._parent.focus.camera.area._yscale = 100;
      this._parent._parent.focus.camera.area._x = 0;
      this._parent._parent.focus.camera.area._y = 0;
      this.camera = 1;
   }
   // of course there may be more than two.
};
// example for Kendra sideways is attached: Normal version for Adobe compiler, FFDec version with removed types and comments because FFDec cannot deal with things that are removed in compilation.
« Last Edit: January 11, 2020, 11:35:20 pm by Tabby »

  • Administrator
  • Sr. Member
  • *****
  • Posts: 407
    • View Profile
Re: Scene Repair
« Reply #65 on: January 11, 2020, 11:32:36 pm »
...and because f u c k i n g Smf boards does not let me increase maximum allowed attachments per post (you can change that in settings but it returns back to 2 after you save that) the example Kendra sideways with that script instead of legacy controller is attached in this additional post.
Easy to not notice change when not looking for that.

Edit: Attachment removed for file space
« Last Edit: July 01, 2020, 10:46:34 pm by Tabby »

  • Hero Member
  • *****
  • Posts: 509
    • View Profile
Re: Scene Repair
« Reply #66 on: January 12, 2020, 04:05:14 am »
Beautiful! I'm going to go over your earlier posts and really try to learn how to incorporate that. It really makes a difference!

  • Hero Member
  • *****
  • Posts: 509
    • View Profile
Re: Scene Repair
« Reply #67 on: January 12, 2020, 07:00:57 pm »
Much easier to implement than Flash. I'm just bad at AS2

  • Hero Member
  • *****
  • Posts: 509
    • View Profile
Re: Scene Repair
« Reply #68 on: April 07, 2020, 08:08:37 pm »
How do I reference different object in AS2? I cannot find an explorer and don't know the object paths.

  • Administrator
  • Sr. Member
  • *****
  • Posts: 407
    • View Profile
Re: Scene Repair
« Reply #69 on: April 07, 2020, 08:40:52 pm »
You have to figure out object tree to find the path from one object to another.
Then you step up the hierarchy by _parent pointer and down the hierarchy by object names in the tree path.

In case some object in the tree does not have a name (possible in SWF) you have to assign it a name in order to make it accessible by AS2 script.
Note that it is the name of object instance where placed, not object class name in a library as one defined object may have multiple copies populated in the tree.

I have no idea how your tool works, I do everything in rudimentary FFDec where I have to figure out object tree in my head manually by tracing PlaceObject() name parameters.

  • Hero Member
  • *****
  • Posts: 509
    • View Profile
Re: Scene Repair
« Reply #70 on: April 08, 2020, 06:29:12 pm »
I'll probably have to do the same in Flash then.

  • Administrator
  • Sr. Member
  • *****
  • Posts: 407
    • View Profile
Re: Scene Repair
« Reply #71 on: April 08, 2020, 10:14:06 pm »
Should you struggle with that, I can do that for you. Just send the file and tell what you want to do.

By the way, I fixed Ginger doggystyle hair animation misalignment. Improved head in her missionary scene. But I wonder if I should somehow rework her pubes in missionary scene? Perhaps much larger? Her lap appears a bit empty.

  • Hero Member
  • *****
  • Posts: 509
    • View Profile
Re: Scene Repair
« Reply #72 on: April 10, 2020, 02:41:31 pm »
I want to figure this out for myself honestly but I appreciate the help.

  • Hero Member
  • *****
  • Posts: 509
    • View Profile
Re: Scene Repair
« Reply #73 on: April 24, 2020, 06:51:25 pm »
I've figured out how to set up the buttons via your script posted earlier, and I am going to implement it into (hopefully) all of the scenes. Before I do that I want to finish the genus implementation. I've redone some of the original drawings I did because they were horrible. I have improved slightly and progress is much faster.