Classic Forums

Please login or register.

Login with username, password and session length
Advanced search  

News:

Graal the Adventure 2004 is now on Graal Reborn! | Introducing Project GrailWay

Pages: [1] 2

Author Topic: How did you accomplish the rising water?  (Read 2734 times)

0 Members and 1 Guest are viewing this topic.

maximus_asinus

  • GC
  • Jr. Member
  • **
  • Posts: 60
    • View Profile
How did you accomplish the rising water?
« on: August 08, 2017, 10:33:08 AM »

I'm trying to replicate the rising water from Link to the Past. How did you accomplish this Thor? Was it a combination of showpoly and changing the zoom (is that even possible?). Or did you create an image and stretch it?
Logged

Thor

  • Manager
  • Sr. Member
  • ****
  • Posts: 452
  • The Higher Power
    • View Profile
Re: How did you accomplish the rising water?
« Reply #1 on: August 09, 2017, 01:21:48 PM »

A combination of showpoly and setshape2.
Logged

maximus_asinus

  • GC
  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Re: How did you accomplish the rising water?
« Reply #2 on: August 10, 2017, 02:59:48 PM »

Maybe you can help me. I am not sure how you moved the showpoly, but I am using the following (tweaked a bit, this is an example).

Code: [Select]
  toPlayerX = playerx - x;
  toPlayerY = playery - y;
  toPlayerLength = (toPlayerX * toPlayerX + toPlayerY * toPlayerY) ^ 0.5;
  toPlayerX = toPlayerX / toPlayerLength;
  toPlayerY = toPlayerY / toPlayerLength;
  x = x + toPlayerX * this.speed;
  y = y + toPlayerY * this.speed;

This has the showpoly moving in a very fluid manner. The problem is it never reaches the exact target coordinates (always off by a few hundredths of a decimal point). This causes some very weird visual glitches where the showpoly will 'bounce' between two coordinates. If I could control the increments (to 0.05 for example) that it moved that would solve my problem, but I don't really understand the math enough to do this. Can you help me out?
Logged

Thor

  • Manager
  • Sr. Member
  • ****
  • Posts: 452
  • The Higher Power
    • View Profile
Re: How did you accomplish the rising water?
« Reply #3 on: August 13, 2017, 04:57:54 AM »

I'm not sure what it is you're trying to accomplish here, as surely the water should rise irrespective of the player's position, unless this is inside a gani script?

What I do is store a tile width and height of the fill area, as well as a filled width and height, and calculate the showpoly x/y/position like so:

Code: [Select]
function updatePoly() {
  temp.x = this.x + this.getWaterX();
  temp.y = this.y + this.getWaterY();
  this.showpoly(200, {temp.x, temp.y, temp.x + this.filledWidth, temp.y, temp.x + this.filledWidth, temp.y + this.filledHeight, temp.x, temp.y + this.filledHeight});
}

function getWaterX()
  return (this.waterWidth - this.filledWidth) / 2;


function getWaterY()
  return (this.waterHeight - this.filledHeight) / 2;
Logged

maximus_asinus

  • GC
  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Re: How did you accomplish the rising water?
« Reply #4 on: August 13, 2017, 07:36:06 PM »

I should have been clear that what I posted was the formula I based the water movement on. This is my original script.

Code: [Select]
//#CLIENTSIDE
function onCreated() {
this.setimg("block.png");
}
function onActionPulled() {
    if (this.waterlevel == 0) {
  this.final = {9,39,47,39,47,27,55,27,55,47,9,47}; // x, y values of where the water starts filling
    this.current = {11,41,49,41,49,29,53,29,53,45,11,45}; // x, y values where the water is finished filling
    }
    else if (this.waterlevel == 1) {
  this.final = {11,41,49,41,49,29,53,29,53,45,11,45};
    this.current ={9,39,47,39,47,27,55,27,55,47,9,47}; 

    }
    this.time = 0;
    this.waterlevel = !this.waterlevel;
    setTimer(0.05);
}
function onTimeout() {
    for (this.a=0;this.a<=this.final.size();this.a++;) {
      this.distx = this.final[0+this.a] - this.current[0+this.a]; // finds the difference between the coordinates in both arrays
      this.disty = this.final[1+this.a] - this.current[1+this.a];
      this.movelength = (this.distx * this.distx + this.disty * this.disty) ^ 0.5; // finds out how many tiles away
      this.distx = this.distx / this.movelength;
      this.disty = this.disty / this.movelength;
      this.current[0+this.a] = this.current[0+this.a] + this.distx * 0.05; // move a step towards the final target
      this.current[1+this.a] = this.current[1+this.a] + this.disty * 0.05;
      showpoly(200,this.current);
      changeimgcolors 200,0,0,1,0.75;
      this.a++;
    }
    setTimer(0.05);
  }
}
Logged

maximus_asinus

  • GC
  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Re: How did you accomplish the rising water?
« Reply #5 on: August 13, 2017, 08:10:57 PM »

Also thanks for replying. I have no scripting experience outside GS1, and it is very frustrating coming against hurdles when there is nobody else willing to help out. It isn't likely I will solve this on my own.
Logged

maximus_asinus

  • GC
  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Re: How did you accomplish the rising water?
« Reply #6 on: August 15, 2017, 05:01:11 PM »

After testing your script visually it only works for square shapes. How would I go about doing other shapes? Like a rectangle? Maybe I am not understanding this script, but it seems very limited.
Logged

Thor

  • Manager
  • Sr. Member
  • ****
  • Posts: 452
  • The Higher Power
    • View Profile
Re: How did you accomplish the rising water?
« Reply #7 on: August 15, 2017, 06:12:23 PM »

After testing your script visually it only works for square shapes. How would I go about doing other shapes? Like a rectangle? Maybe I am not understanding this script, but it seems very limited.

All this code does is handle the drawing of the polygon based on the water-filled area compared with the total flood-able area, but it can and does work for rectangular areas too, rectangles just require specific math to increment the filled area as the filled width and height would not increment evenly.

When raising the water I increment the areas like so:

Code: [Select]
  temp.w = this.waterWidth - (this.boundaryWidth * 2);
  temp.h = this.waterHeight - (this.boundaryWidth * 2);
  temp.xIncrease = 50;
  temp.yIncrease = 50;

  if (this.boundaryWidth > 0) {

    if (this.waterWidth - this.filledWidth <= this.boundaryWidth * 2) {
      temp.w = this.boundaryWidth;
      temp.xIncrease /= 2;
    }

    if (this.waterHeight - this.filledHeight <= this.boundaryWidth * 2) {
      temp.h = this.boundaryWidth;
      temp.yIncrease /= 2;
    }

  }
  temp.xIncrease = (temp.w / temp.xIncrease);
  temp.yIncrease = (temp.h / temp.yIncrease);
  this.filledWidth = min(this.waterWidth, this.filledWidth + temp.xIncrease);
  this.filledHeight = min(this.waterHeight, this.filledHeight + temp.yIncrease);
  this.updatePoly();

(Boundary width would be the walled area on the outermost tiles of a fill area, where I have the water raise more slowly)
Logged

maximus_asinus

  • GC
  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Re: How did you accomplish the rising water?
« Reply #8 on: August 15, 2017, 10:01:42 PM »

Okay I've run what you gave me and it works, though it looks a bit odd when you're flooding in long skinny sections. Also how would you handle two intersecting flows of water? I am demoing in an L shaped room and want to flood both sections. Here is a demo of what I am talking about.

https://www.youtube.com/watch?v=cj6dqNfGnMw

I'm assuming it was luck that they came together at the same time.

Could this be done with one source of water instead of adding multiple?




Logged

maximus_asinus

  • GC
  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Re: How did you accomplish the rising water?
« Reply #9 on: August 15, 2017, 11:20:16 PM »

Also can you explain how attachplayertoobj works online?

Offline if I use attachplayertoobj it acts as if the player is on a layer above the tileset and ignores blocking tiles. In combination with setshape2 I can make blocking tiles swimmable.

Code: [Select]
if (created) {
  setshape2 2,2,{11,11,11,11};
}
if (playertouchsme) {
  attachplayertoobj 0,id;
}

With the same script (updated to GS2 obviously) the tiles are still swimmable but it doesn't put me on that separate layer.

Code: [Select]
//#CLIENTSIDE
function onCreated() {
setshape2(2,2,{11,11,11,11});
}
function onPlayerTouchsMe() {
attachplayertoob(0, id);
}

And again, thanks for your patience. I am learning a lot from what you've shown me so far. I appreciate the help.
« Last Edit: August 15, 2017, 11:26:35 PM by maximus_asinus »
Logged

maximus_asinus

  • GC
  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Re: How did you accomplish the rising water?
« Reply #10 on: August 17, 2017, 06:28:46 PM »

Maybe you can answer me. This my post from the other forums:

Quote
is it possible for two classes to communicate?

My example:

In the first class I have a switch that the player interacts with by swinging the sword. This class is supposed to tell the second class that it was hit. In the second class I have blocks that raise or lower depending on the status of the switch.

I can do a hack solution like a check in a looping timeout but I feel like this can be done with a trigger, and I don't want to use triggeraction if I have 20 different blocks. Want to make something that will allow me to just drag-and-drop these for the most part.
« Last Edit: August 17, 2017, 10:37:54 PM by maximus_asinus »
Logged

maximus_asinus

  • GC
  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Re: How did you accomplish the rising water?
« Reply #11 on: August 17, 2017, 10:36:43 PM »

Quick update:

I went back and tried public function again after reading a post by fp4 and got something that ALMOST works.

CLASS A
Code: [Select]
//#CLIENTSIDE
function onActionAHPhit() { // custom sword hit detection
  temp.foobar = this.level.foobar;
  temp.foobar.baz();
}
 
CLASS B
Code: [Select]
//#CLIENTSIDE
function onCreated() {
  this.setimg("block.png");
  this.level.foobar = this;
}
public function baz() {
  this.chat = "debug";
}

The problem is only the last NPC to join Class B will receive the update. If I could get around that I would be all set.
Logged

Thor

  • Manager
  • Sr. Member
  • ****
  • Posts: 452
  • The Higher Power
    • View Profile
Re: How did you accomplish the rising water?
« Reply #12 on: August 18, 2017, 01:30:31 PM »

Seems awkward to post about this here unless it's specific to Classic.

I posted a reply at http://forums.graalonline.com/forums/showthread.php?p=1741824#post1741824
Logged

maximus_asinus

  • GC
  • Jr. Member
  • **
  • Posts: 60
    • View Profile
Re: How did you accomplish the rising water?
« Reply #13 on: August 20, 2017, 01:21:42 AM »

Sorry to bring this back up. I'm not sure if this is appropriate to talk about here or if I should ask these questions on the other forum.

I've been reviewing the water script and I finally got to a point where I somewhat understand what is happening. I tried to add on draining functionality (which works) but it is definitely hacked together. Do you have any advice on how to clean this up?

Code: [Select]
// setting variables and giving the object a name

function onCreated() {
  this.waterWidth = 24;
  this.waterHeight = 8;
  this.boundaryWidth = 2;
  this.boundaryHeight = 2;
  this.level.foobar = this;
}

// designed to show proper water level if the player were to log off.
// using client variable to save status

function onPlayerEnters() {
  if (client.waterfilled = true) {
    this.showpoly(200, {this.x, this.y, this.x + this.waterWidth, this.y, this.x + this.waterWidth, this.y + this.waterHeight, this.x, this.y + this.waterHeight});
    this.changeimgcolors(200,0,0,1,0.75);
    this.changeimgvis(200,1);
  }
  else this.hideimg(200);
}

// triggering public function from a switch in the level.
// using it this way so I can break a nested timeout.

public function watercheck() {
  if (client.waterfilled == true) {
    this.filledHeight = 0;
    this.filledWidth = 0;
  }
  else {
    this.filledHeight = this.waterHeight;
    this.filledWidth = this.waterWidth;
  }
  setTimer(0.05);
}

function onTimeout() {
  waterAction();
  setTimer(0.1);
}

function waterAction() {

// the truly hacked part
// enabling and disabling the movement and breaking the timeout once the water is finished it's thing

  if (client.waterfilled == true) {
    if (this.waterWidth == this.filledWidth && this.waterHeight == this.filledHeight) {
      disablescriptmovement = false;
      return;
    }
    else  disablescriptmovement = true;
  }
  if (client.waterfilled ==  false) {
    if (this.filledWidth <= 0 && this.filledHeight <= 0) {
      disablescriptmovement = false;
      return;
    }
    else  disablescriptmovement = true;
  }
  temp.w = this.waterWidth - (this.boundaryWidth * 2);
  temp.h = this.waterHeight - (this.boundaryHeight * 2);
  this.xIncrease = 50;
  this.yIncrease = 50;
  if (this.boundaryWidth > 0) {
    if (this.waterWidth - this.filledWidth <= this.boundaryWidth * 2) {
      temp.w = this.boundaryWidth;
      this.xIncrease /= 2;
    }
    if (this.waterHeight - this.filledHeight <= this.boundaryHeight * 2) {
      temp.h = this.boundaryHeight;
      this.yIncrease /= 2;
    }
  }
  this.xIncrease = (temp.w / this.xIncrease);
  this.yIncrease = (temp.h / this.yIncrease);

// checking whether to flood or empty the room

  if (client.waterfilled = true) {
    this.filledWidth = min(this.waterWidth, this.filledWidth + this.xIncrease);
    this.filledHeight = min(this.waterHeight, this.filledHeight + this.yIncrease);
  }
  else {
    this.filledWidth = min(this.waterWidth, this.filledWidth - this.xIncrease);
    this.filledHeight = min(this.waterHeight, this.filledHeight - this.yIncrease);
  }
  updatePoly();
}

// drawing the polygon

function updatePoly() {
  temp.x = this.x + this.getWaterX();
  temp.y = this.y + this.getWaterY();
  this.showpoly(200, {temp.x, temp.y, temp.x + this.filledWidth, temp.y, temp.x + this.filledWidth, temp.y + this.filledHeight, temp.x, temp.y + this.filledHeight});
  this.changeimgcolors(200,0,0,1,0.75);
  this.changeimgvis(200,1);
}

function getWaterX() {
  return (this.waterWidth - this.filledWidth) / 2;
}

function getWaterY() {
  return (this.waterHeight - this.filledHeight) / 2;
}
Logged

Thor

  • Manager
  • Sr. Member
  • ****
  • Posts: 452
  • The Higher Power
    • View Profile
Re: How did you accomplish the rising water?
« Reply #14 on: August 20, 2017, 06:19:28 AM »

Code: [Select]
function onPlayerEnters() {
  if (client.waterfilled = true) {

Using a single = will always treat the conditional as TRUE, it should be ==. Better yet if you're storing boolean values (true/false or 1/0) you can just do:

Code: [Select]
function onPlayerEnters() {
  if (client.waterfilled) {

or

Code: [Select]
function onPlayerEnters() {
  if (!client.waterfilled) {

--------

Rather than use a timeout I use scheduleEvent(), which can be cancelled with cancelEvents("action").

Code: [Select]

function onFillWater() {
  //blah blah
  this.scheduleEvent(0.2, "FillWater");
}

function onDrainWater() {
  //blah blah
  this.scheduleEvent(0.2, "DrainWater");
}

function stopFill() {
  //blah blah
  this.cancelEvents("FillWater");
}

function stopDrain() {
  //blah blah
  this.cancelEvents("DrainWater");
}

Logged
Pages: [1] 2