Help with board game (SOLVED)

Started by Maverick, Wed 09/08/2006 21:18:42

Previous topic - Next topic

Maverick

I want to make a very basic board game where the objective is to move one object to a specifc point before it is intersected by another object.

Object 1 (only object that can be manipulated by the player) can only move one block at a time, either horizontal or vertical. Movement to be initiated by clicking (left click) on the square you want to move to.

Object 2 - once object one has made its move it must move two squares at a time and it must try to intercept object one (if object 2 catches up with object 1 the game is lost)). It must always move horizontally on its first move unless its path is blocked by something (wall) in which case object 2 will move vertically first and then try to move horizontally on the second move. If it end up on the same horizontal row as object one but its path is obstructed then it will not move any further (same applies for vertical obstruction) . If it ends up behind an obstruction and object 1 is on the same horizontal row it should not advance anywhere and object 1 will have another turn to move. This status should remain untill object 1 makes a vertical move that will trigger object 2 to move out from behind the obstruction.

I know it is a mouth full but I'm looking for the basic commands to use to get the "player" object to move to the square that it click on. (I'm not looking for someone to do it for me. I just need someone to point me in the right direction)

Grid for the game is a basic chess board (8x8 squares) of 40x40

Ishmael

If you're not experienced in scripting I suggest you go through the scripting tutorial in the manual and poke around the default game template and possibly other templates and open source projects out there to see how things are done by other people.

As for the functionality of the board, you can either use on_mouse_click in the room script and check for mouse co-ordinates on click, and issue an Object.Move command based on that, or paint hotspots on the grid and have them all trigger the same script function, which moves the object appropriately.

What I can tell you, is that you most likely need a fair amount of if-statements.
I used to make games but then I took an IRC in the knee.

<Calin> Ishmael looks awesome all the time
\( Ö)/ ¬(Ö ) | Ja minähän en keskellä kirkasta päivää lähden minnekään juoksentelemaan ilman housuja.

Maverick

Thanks Ishmael

Quote from: Ishmael on Thu 10/08/2006 11:35:26
If you're not experienced in scripting I suggest you go through the scripting tutorial in the manual and poke around the default game template and possibly other templates and open source projects out there to see how things are done by other people.

I know just enough about code not to hurt myself but I'm getting there.

Quote from: Ishmael on Thu 10/08/2006 11:35:26
As for the functionality of the board, you can either use on_mouse_click in the room script and check for mouse co-ordinates on click,

I could not pick up anything that would return the mouse X and Y coords on the mouse click event for input into the object.Move command.Ã, 

Quote from: Ishmael on Thu 10/08/2006 11:35:26

or paint hotspots on the grid and have them all trigger the same script function, which moves the object appropriately.

Am I mistaken in thinking that the number of hotspots are limited to much less than 64 (30 I think)?

Quote from: Ishmael on Thu 10/08/2006 11:35:26

What I can tell you, is that you most likely need a fair amount of if-statements.

The logical statements is one topic I actually understand !

Thanks again!


SSH

You coudl calulate the square clicked on from the x and Y mouse co-ords, then calculate the centre of the square and move the character to that point. That would also avoid having to paint lots of hotspots, and any limit on the number of hotspots.
12

Ishmael

Quote from: Maverick on Thu 10/08/2006 12:35:51
I could not pick up anything that would return the mouse X and Y coords on the mouse click event for input into the object.Move command.Ã, 

Global variables mouse.x and mouse.y do the trick.
I used to make games but then I took an IRC in the knee.

<Calin> Ishmael looks awesome all the time
\( Ö)/ ¬(Ö ) | Ja minähän en keskellä kirkasta päivää lähden minnekään juoksentelemaan ilman housuja.

Maverick

Quote from: SSH on Thu 10/08/2006 12:41:55
You coudl calulate the square clicked on from the x and Y mouse co-ords, then calculate the centre of the square and move the character to that point. That would also avoid having to paint lots of hotspots, and any limit on the number of hotspots.

This is exactly the point where I get a headache. ;D
It sounds like a great idea but I wouldn't know how to go about it. It would definately solve the problem because using the mouse.x and mouse.y position on_mouse_click event will not centre the object in the adjacent block but would rather move it to the exact spot the player clicked on (I think). Can you elaborate a little on the HOW TO or even point me at something in the manual that might help?

Thanks

Wretched

Macerick,
As requested. In Zugzwang I used two Screens, one with Hotspots and one with Regions. I read both on a mouse click. The Hotspots gives me the Board X value and Regions the Board Y value.



To get the centre of each square I took the coordinates of the centres of the 4 corner squares then use this;

Code: ags

float BX0=58.0;Ã,  Ã,  Ã,  Ã,  //X value centre top left square
float BX1=256.0;Ã,  Ã,  Ã,  //X Value centre top right square
float BX2=20.0;Ã,  Ã,  Ã,  Ã,  //X Value centre bottom left square
float BX3=299.0;Ã,  Ã,  Ã,  //X Value centre rottom right square

int SX;Ã,  Ã,  Ã,  Ã, //Final Screen X 
int SY;Ã,  Ã,  Ã,  Ã, //Final Screen Y
float SScale;Ã,  Ã, //Scale of piece for mock 3D effect

function ScreenXY(int x, int y)Ã,  Ã, //Board (x,y)Ã,  Ã,  (0,0) is top left
{
Ã,  if (y==0) SY=220;Ã,  Ã,  //Get Screen Y values for vertical centre of each square
Ã,  if (y==1) SY=195;
Ã,  if (y==2) SY=171;
Ã,  if (y==3) SY=150;
Ã,  if (y==4) SY=129;
Ã,  if (y==5) SY=110;
Ã,  if (y==6) SY=94;
Ã,  if (y==7) SY=81;

Ã,  //Calculate Screen X values assuming linearly spaced squares
Ã,  float kx;
Ã,  float ky;
Ã,  float x0;
Ã,  float x1;
Ã,  
Ã,  ky=1.0-(IntToFloat(SY)-81.0)/(225.0-89.0);Ã,  //ky=1.0 at bottom =0.0 at top
Ã,  
Ã,  x0=BX2+ky*(BX0-BX2);
Ã,  x1=BX3+ky*(BX1-BX3);
Ã,  
Ã,  kx=(IntToFloat(x))/(IntToFloat(BoardSize-1));
Ã,  SX=FloatToInt(x0+kx*(x1-x0));
Ã,  
Ã,  SScale=(100.0+(70.0-100.0)*ky)/100.0;Ã,  //Scale calculation to give mock 3D effect based on ky
}



Now have SX and SY as screen coord for Square centres.

Sorry it's so messy was coded in very short amout of time. This can be used to effectivly get 256 screen hotspots.

Same code would work for a 2D board. But then it would be easier to just use the mouse x,y values
e.g.
SX=SquareLeftCentreX+((mouse.x-SquareLeftCentreX)/SquareWidth)+(SquareWidth/2);
and similar for Y.

Maverick

Quote from: Wretched on Thu 10/08/2006 21:42:35
In Zugzwang I used two Screens, one with Hotspots and one with Regions. I read both on a mouse click. The Hotspots gives me the Board X value and Regions the Board Y value.
I don't get what you mean by "using 2 screens"? The regions and hotspots are drawn on separate backgrounds, different rooms ?
Quote from: Wretched on Thu 10/08/2006 21:42:35

function ScreenXY(int x, int y)Ã,  Ã, //Board (x,y)Ã,  Ã,  (0,0) is top left
{
Ã,  if (y==0) SY=220;Ã,  Ã,  //Get Screen Y values for vertical centre of each square
Ã,  if (y==1) SY=195;
Ã,  if (y==2) SY=171;
Ã,  if (y==3) SY=150;
Ã,  if (y==4) SY=129;
Ã,  if (y==5) SY=110;
Ã,  if (y==6) SY=94;
Ã,  if (y==7) SY=81;

I think I understand the part where SY is initialized to eg. SY=81 (calculated based on the height of the squares on the background) but I don't get the part if(y==0) etc.
I understand that it is linked to the region or hotspot assigned in a specific row (depending on what you used for the y valuesi.e hotspot or region) but have no idea how it is linked.
Quote from: Wretched on Thu 10/08/2006 21:42:35
Ã,  ky=1.0-(IntToFloat(SY)-81.0)/(225.0-89.0);Ã,  //ky=1.0 at bottom =0.0 at top
Ã, 
Can you elaborate on what value you used for the calculations.
Quote from: Wretched on Thu 10/08/2006 21:42:35
Ã,  kx=(IntToFloat(x))/(IntToFloat(BoardSize-1));

I couldn't find anything on the BoardSize variable that was used here (was not declared)

Thanks for the help so far I appreciate the effort!

Wretched

Hi Maverick,
Sorry I didn't realise this was in the Beginners section when I posted hence I assumed rather a lot.

The idea is to use the HotSpots and Regions as two seperate masks that work together, You use (Version 2.72 code)

Code: ags

function on_mouse_click(MouseButton button) // called when a mouse button is clicked. button is either LEFT or RIGHT
{
Ã,  Hotspot* Hot;
Ã,  Region* Reg;

Ã,  if (button==eMouseLeft)
Ã,  {
Ã, Ã,  Ã, Hot=Hotspot.GetAtScreenXY(mouse.x,mouse.y);Ã,  
Ã, Ã,  Ã, Reg=Region.GetAtRoomXY(mouse.x, mouse.y);

Ã,  Ã,  if (Hot.ID!=0 && Reg.ID!=0)
Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã, BoardSquareX=Hot.ID-1;
Ã,  Ã,  Ã,  Ã, BoardSquareY=Reg.ID-1;
Ã,  Ã,  Ã,  Ã, ClickOnBoard=true;
Ã,  Ã,  }
Ã,  Ã,  else
Ã,  Ã,  {
Ã,  Ã,  Ã,  ClickOnBoard=false;
Ã,  Ã,  }

}


function ScreenXY(int x,int y), is to calculate the centre of the squares in screen space, from the Board X,Y position . Sorry I got the board upside down, (0,0) is the bottom left corner. Might be better to change the function to ScreenXY(int BoardX,int BoardY), to be clearer.

All the 'if's just convert the Board Y value to the corresponding Screen Y values for the vertical cantres of the squares.

Code: ags

  ky=1.0-(IntToFloat(SY)-81.0)/(220.0-81.0);  //ky=1.0 at bottom, ky=0.0 at top
    //81.0 is vertical centre of top row
    //220.0 is vertical centre of bottom row

This gives me a float (ky) that is 0.0 at the top of the board and 1.0 at the bottom of the board, the Values are just taken from the list of ifs above.


Code: ags

Ã,  kx=(IntToFloat(x))/(IntToFloat(BoardSize-1));

This gives me a float (kx) that is 0.0 at the left of the board and 1.0 at the right of the board.
Sorry BoardSize is the size of the Board, so 8 in my case. (as 8x8 Board). Actually would be better to use BoardSizeX in case you have a rectangular board.


Maverick

#9
Wretched,
Quote from: Wretched on Mon 14/08/2006 07:47:34
The idea is to use the HotSpots and Regions as two seperate masks that work together, You use (Version 2.72 code)

I'm using Version 2.71 but I do not think that is a huge problem as everything so far is pretty much the same for both versions and I'll change it where necessary.

Quote from: Wretched on Mon 14/08/2006 07:47:34

function on_mouse_click(MouseButton button) // called when a mouse button is clicked. button is either LEFT or RIGHT
{
Ã,  Hotspot* Hot;
Ã,  Region* Reg;

Ã,  if (button==eMouseLeft)
Ã,  {
Ã, Ã,  Ã, Hot=Hotspot.GetAtScreenXY(mouse.x,mouse.y);Ã, 
Ã, Ã,  Ã, Reg=Region.GetAtRoomXY(mouse.x, mouse.y);

Ã,  Ã,  if (Hot.ID!=0 && Reg.ID!=0)
Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã, BoardSquareX=Hot.ID-1;
Ã,  Ã,  Ã,  Ã, BoardSquareY=Reg.ID-1;
Ã,  Ã,  Ã,  Ã, ClickOnBoard=true;
Ã,  Ã,  }
Ã,  Ã,  else
Ã,  Ã,  {
Ã,  Ã,  Ã,  ClickOnBoard=false;
Ã,  Ã,  }
}


I understand this part but just cannot figure out why you used this:
BoardSquareX=Hot.ID-1; // Why theÃ,  -1?
BoardSquareY=Reg.ID-1;// Why the - 1?

The way I understand the above code is that BoardSquare X = the hotspot found at the screen XY's ID less one. If it happens to be Hotspot 1 then you'll come up with Hotspot 0 which does not exist. So if the object I want to move is one square A1 (assuming it is bottom left) and I click on A2 (going up on the vertical) it won't go anywhere.

Quote from: Wretched on Mon 14/08/2006 07:47:34

Ã,  ky=1.0-(IntToFloat(SY)-81.0)/(220.0-81.0);Ã,  //ky=1.0 at bottom, ky=0.0 at top
Ã,  Ã,  //81.0 is vertical centre of top row
Ã,  Ã,  //220.0 is vertical centre of bottom row

Now I get it. The (225.0 - 89.0) in the initial code confused me because it was different from the values assigned in the function: function Screen XY(int x, int y).

Quote from: Wretched on Mon 14/08/2006 07:47:34
Ã,  kx=(IntToFloat(x))/(IntToFloat(BoardSize-1));

This gives me a float (kx) that is 0.0 at the left of the board and 1.0 at the right of the board.
Sorry BoardSize is the size of the Board, so 8 in my case. (as 8x8 Board). Actually would be better to use BoardSizeX in case you have a rectangular board.

Am I correct in saying that I just have to declare an int variable and initialize it to e.g
BoardSize = 8; // I'm using a standard 8x8 square board

I know some of my question seem pretty basic to an expert like you but I just hate using something if I do not understand exactly what its about. If I do not learn from it I might as well ask someone to just make the game for me. Be that as it may I'm sure that I'm boring and or anoying some of the other members, so if you don't mind couching me on this through PM I would appreciate it.

Thanks!

Maverick

#10
Before the sky comes down on me, yes I know not to double post but I took this thread to PM with Wretched so he could explain a few things to me that I didn't understand. Seems there was more than just a bit and he would probably spend the next few days in rehab after this. Sorry Wretched!!

What I have managed to sort out at this point is to convert the Hotspots and Regions to BoardX and Y coords and then from BoardX and Y coords to SreenX an Y coords. I tested this with the display function and all seems to be working fine. Now I have to set up and array or struct to track the objects on the board and needless to say I have only a very faint idea of what it entails. Just to make it easier to assist me, this is the board I'm using (just a test)


(Thanks Neole)

BoardX = 0 at the bottom left square and 7 at bottom right square
Board Y =0 at bottom squares and 7 at top squares

What I have done so far:

In the main header script
Code: ags

struct sBoardSquare {
Ã,  int gamepiece;
Ã,  bool up;
Ã,  bool down;
Ã,  bool left;
Ã,  bool right;
Ã,  
};

import sBoardSquare Board[64];



In the main global script
Code: ags

sBoardSquare Board[64];


#sectionstart game_startÃ,  // DO NOT EDIT OR REMOVE THIS LINE
function game_start() {
Ã,  // called when the game starts, before the first room is loaded

Code: ags

Ã,  
Board[0].gamepiece = 0;
Board[0].down = false;
Board[0].left = false;
Board[0].right = false;
Board[0].up = false;

.....

Board[63].gamepiece = 0;
 Board[63].down = false;
Board[63].left = true;
Board[63].right = false;
Board[63].up = true;
	Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  }
export Board;

Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã,  Ã, 
This gives me the 64 squares on an 8 x 8 board (think I got them the wrong way round, Board[0] should be bottom left square and not top left, I think)

The problem is that there is no link to the actual squares..can I use this in the main global script to index the board?
Code: ags

sBoardSquare Board[BoardSquareY*BoardSize+BoardSquareX];


Looks like it should work but wouldn't that mean that I have to declare a different struct to keep track of the up,down,left,right restrictions?
How would I track the movement of the gamepiece as it moves around?

Any help would be appreciated.
Just in case anyone is wondering, yes I checked every single thread and the above code is the best I can do with what I've learned.Ã,  :P

SMF spam blocked by CleanTalk