How do I get an object to interact with a hotspot?

Started by bx83, Sun 27/06/2021 14:19:43

Previous topic - Next topic

bx83

I've started a Pacman-like 'minigame' on an 'arcade machine' in whick a Tank (you) - using arrow keys to get around the maze - is following crowds (AI/enemies). Your mission - to crush the protesting crowds before a) the timer runs out and/or b) before they destroy your tank from behind with molatovs.

I've come up with I think a reasonable strategy or programming the crowds where to go; there are 10-15 types of hotspot, each with the directions a crowd can choose to go in (UpLeft, DownRight, UpLeftDown, etc.), pasted over all corners of the maze. They can then go in one of the directions, depending on which way the Tank is, and which direction he's going in (towards=fear, away=attack).

Only problem is:
-I don't know if this is actually a crap strategy
-and I don't know how you get anything but an object interacting with another object. You can get a character 'sandng on' a hotspot, but not an object.

There's a limit of 40 on-screen objects; yet if I put in 'decision cube' sprites with objects to replace the hotspots, there's waaaay more than 40 (about 75?).

Pls halp I don't know wha I'm doing :/

eri0o

When using the AGS abstractions, you either should design with them in mind or use something like the Object Pool module if you can work without having all the elements being shown on the screen all the time (like with a fog of war, or dividing the maze in zones so that just a zone is on the screen). Btw, you can use characters as objects and characters are unlimited.

IF the art style in the arcade can get away with something more pixely (this a big IF, if not, disregard everything I say forward), then I would suggest avoiding AGS common abstractions and instead code your own and use a Dynamic Sprite as the screen you will blit your arcade elements, and then placing the sprite (.Graphic property of the dynamic sprite) in an object and using a room with a camera to zoom on this object (which will use your GPU HW acceleration to do so), so in this way the object would be the screen of the arcade.

Dynamic Sprite will be using bitmap (raster) drawing functions on the CPU, so they are slow (this is why I mentioned working on a pixely low resolution for the arcade, like 320x180 or below). But the benefit of doing so is you have total control of the renderer, and then all the game logic you can code without any limits.

bx83

Okay, very informative; but how do I make hotspots interactive with anything? Just characters instead of objects sounds like a good idea..?

The game unfortunately is 1366x768 and not pixeley enough.

eri0o

So by interacting I think you mean detecting like someone that's not the player touched something? I think you will endup needing to check for this in repeatedly execute. Test one pixel of each element using the hotspot functions in the API to see if one is touching it and resolve however you see fit.

AGS has some very brute collision tests you can use (for object/character interaction) but if they don't work as you expect you can code your own, like AreThingsOverlapping and Object.IsCollidingWithObject, but there are more of these lost in the API, need to check in the manual...

bx83

Something tells me this function won't work... but how else do I get the hotspot ID/character ID?
I'm using named Characters (cC1, cC2 etc.) to represent protestors, and hotspots to represent different classes of directions (eg. green squares = hHotspot3 = the 'DownLeft' choices of next direction.

Code: ags
//arguments: takes the character walking over a hotspot 'ch', the hotspot itself 'hs', x/y coords (ie. of tank)
//result: decides which new direction is the shortest line between the ch.x,y and tank x,y, chooses this as new direction
function ChooseDirectionBasedOnDisanceToTank(character ch, hotspot hs, int x, int y)
{
  //down:
  if (hs.ID==3 || hs.ID == 6 hs.ID==7 || hs.ID==11 || hs.ID==14 || hs.ID==15) {    //hotspots that contain down as direction
    //todo: write (ch.x, ch.y+10) coords into decision
  }
  //up
  if (hs.ID==9 || ....
    //todo: write (ch.x, ch.y-10) coords
  }

  //todo: review array, find smallest dx,dy line joining x,y and ch.xy, choose direction
}

//hotspot functions
function hDownLeft_WalkOn()
{
  if (character.ID>=59 && character.ID<=63) {  //one of the 5 'crowds'
    if (hotspot.ID!=character.GetProperty("AG_current_hotspot") && hotspot.ID>0) {
      ChooseDirectionBasedOnDisanceToTank(character.ID, hotspot.ID, x, y);
    }
  }
}



Khris

Use a grid. AGS doesn't support two-dimensional arrays, but that's not a big problem to solve.

For instance a 15x10 grid can be represented using int g[150];.
This creates an array of 150 zeroes.

To get from x/y to the index (all zero-based), you use i = y * number_of_rows + x;
To get from an index i to x and y, you use  x = i % number_of_columns;  and  y = i / number_of_columns;

Next you keep coordinates and a direction for each crowd, and move them from cell to cell. Each x frames, when they arrive at the center of a cell, you check if there's a wall in the current direction and randomly find a new, free direction for them to walk in.

bx83

Okie doke.
Do you happen to know how I could create an array of structs?
ie:

GlobalScript: (I presume? though game and all variables are in a room...)

Code: ags
struct Grid {
  int x;
  int y;
  String refName;
  bool up;
  bool right;
  bool down;
  bool left;
};

#define numRows  8
#define numCols   10

//10 rows * 8 columns
Grid *theGrid[numRows*numCols];

Grid SetupValues()
{
  theGrid[0].x=0; theGrid[0].y=0; theGrid[0].refName="00"; theGrid[0].up=0; theGrid[0].right=1; theGrid[0].down=0; theGrid[0].left=1; //0,0
  theGrid[1].x=0; theGrid[1].y=0; theGrid[1].refName="01"; theGrid[1].up=1; theGrid[1].right=1; theGrid[1].down=0; theGrid[1].left=1; //0,1
  ......
}

Grid* XYToIndex(int x, int y)
{
  //note for ref 52, x=5, y=2
  return theGrid[y*numRows+x];
}


function IndexToXY(int i)
{
  return theGrid[(i % numCols)*(i / numCols)];
}



ps my grid is of the form:
50px square each grid reference

00 01 02 03 04 05 06 07 08 09
10 11 12 13 14 15 16 17 18 19
20 21 22 ....

corresponding to 50px x 50px squares of the graphical map.

So... does the above make any sense in logic or syntax? I'm flying blind but trying.

SMF spam blocked by CleanTalk