Hey all,
I'm new to AS3 and I was making a game of chess. Basically whenever you click a square with a chess piece, I assumed it would be like java, and you'd be able to create an "ActionListener" that would pass a reference to a square that was clicked.
My question is this: How can I access this square object that was clicked in my array?
board[x1][y1].addEventListener(MouseEvent.CLICK, onClick);
because I can make a function "onClick" but I will have no access to the object board[x1][y1] (the square object).
I'd like to do something like this...where my x's and y's would be the x1 and y1 of the board[x1][y1]
public function onClick(ev:MouseEvent): void
{
var x:Number = ev.THE X OF THE OBJECT?
var y:Number = ev.THE Y OF THE OBJECT?
trace(x);
//If there's a piece that is clicked.
if (board[x][y].piece != null)
{
//If an ally piece is clicked,
if (game.currentPlayer().white && board[x][y].piece.isWhite)
{
selected = board[x][y];
trace(selected.name);
}
}
//Moving to an empty spot
if (board[x][y].piece == null && selected != null)
{
selected.moveToSquare(board[x][y]);
//Switch players
game.playerOne.active = !game.playerOne.active;
game.playerTwo.active = !game.playerTwo.active;
}
//Kill enemy
if (board[x][y].piece != null && selected.piece != null)
{
if (board[x][y].piece.isWhite && !selected.piece.isWhite)
{
selected.moveToSquare(board[x][y]);
//Switch players
game.playerOne.active = !game.playerOne.active;
game.playerTwo.active = !game.playerTwo.active;
}
}
//Deselecting a piece
if (board[x][y] == selected)
{
selected = null;
}
}
If you could maybe point me in the right direction, I'd appreciate it :) This has me pretty frustrated. If you need additional information, I'd be glad to share more of my code.
There are tons of ways to do this :-)
First of all, remember that dispatchEvent (function which sends events) and addEventListener implementation are part of EventDispatcher class. This means that all objects of EventDispatcher class or its subclasses (includes most of flash.display.* classes) can send events and register "listeners" (functions that are called when event happens).
In your case, I don't see which of your objects, if any, implements event dispatching or extends EventDispatcher class, or includes a property that is an event dispatcher.
I assume, since you say your board squares can be clicked, they are visual objects. If they are, each of them can send events and register Listeners. You can choose if you want 8x8=64 event dispatchers, or you can do another thing - for your board class, which I assume is a display object too, create an "event_dispatcher: EventDispatcher" object, or inherit the whole class from EventDispatcher. Then, relying on the three event phases - capturing/target/bubbling, and an extended BoardSquare class, do something like:
//Each of your board squares now can have x and y values, which you assign when you create the board.
class ChessBoardSquare extends Sprite //event dispatcher too, but not used now
{
var x: Int;
var y: Int;
}
class ChessBoard extends Sprite //this is an event dispatcher, because Sprite is
{
function new()
{
build();
init();
}
function build()
{
//Add those squares
for(var x = 0; x < 8; x++)
for(var y = 0; y < 8; y++)
{
var square = new ChessBoardSquare();
square.x = x;
square.y = y;
//Make sure the square is also of the right color :-)
addChild(square);
}
}
function init()
{
//board is display object and will respond to "clicks" from any display object below it - including, but not limited to, squares
addEventListener("click", on_click);
}
//Might happen for any object below the board (even the board itself), not just a ChessBoardSquare
function on_click_event(e: Event)
{
if(e.target instanceof ChessBoardSquare)
{
//obviously a square was clicked, not anything else (which does send events too!)
on_click_square(e);
}
}
//Sending e just in case you wanted some more event properties, like some mouse properties f.e.
function on_click_square(e: Event)
{
var square = e.target;
var x = square.x;
var y = square.y;
//That code you posted that wanted to work...
}
}
There are many other ways to do this, and MANY optimizations you can do. All depending on what you want and what you weigh as important.
I found out yesterday that an event dispatcher is 48 bytes in memory. Not of any importance for chess games and squares that dispatch events, but for a fluid dynamics simulation it may be :-) Don't optimize until your game works.
In case you wanted a more professional reply, remember that you can extend Event class and dispatch your own event objects, of your Event subclass, around. These objects can have their own properties, naturally. Why not x, and y?
Event.target already carries an object reference. The problem is you cannot add properties to "sealed" classes (you get a runtime exception error), which all classes are, unless specified otherwise. And unless your event target is an object that actually has x and y properties, it is more difficult to extract such values just from a Sprite.
Here's my board class:
public class Board extends Sprite
{
var board:Array = new Array(8);
var selected:Square;
var game:Game;
public function Board(currentGame:Game)
{
this.game = currentGame;
for (var y: Number = 0; y < 8; y++)
{
board[y] = new Array(8);
}
board[0][0] = new Square(new Piece(this, "rook", false), 0, 0, this);
board[1][0] = new Square(new Piece(this, "knight", false), 1, 0, this);
board[2][0] = new Square(new Piece(this, "bishop", false), 2, 0, this);
board[3][0] = new Square(new Piece(this, "queen", false), 3, 0, this);
board[4][0] = new Square(new Piece(this, "king", false), 4, 0, this);
board[5][0] = new Square(new Piece(this, "bishop", false), 5, 0, this);
board[6][0] = new Square(new Piece(this, "knight", false), 6, 0, this);
board[7][0] = new Square(new Piece(this, "rook", false), 7, 0, this);
board[0][1] = new Square(new Piece(this, "pawn", false), 0, 1, this);
board[1][1] = new Square(new Piece(this, "pawn", false), 1, 1, this);
board[2][1] = new Square(new Piece(this, "pawn", false), 2, 1, this);
board[3][1] = new Square(new Piece(this, "pawn", false), 3, 1, this);
board[4][1] = new Square(new Piece(this, "pawn", false), 4, 1, this);
board[5][1] = new Square(new Piece(this, "pawn", false), 5, 1, this);
board[6][1] = new Square(new Piece(this, "pawn", false), 6, 1, this);
board[7][1] = new Square(new Piece(this, "pawn", false), 7, 1, this);
board[0][7] = new Square(new Piece(this, "rook", false), 0, 7, this);
board[1][7] = new Square(new Piece(this, "knight", false), 1, 7, this);
board[2][7] = new Square(new Piece(this, "bishop", false), 2, 7, this);
board[3][7] = new Square(new Piece(this, "queen", false), 3, 7, this);
board[4][7] = new Square(new Piece(this, "king", false), 4, 7, this);
board[5][7] = new Square(new Piece(this, "bishop", false), 5, 7, this);
board[6][7] = new Square(new Piece(this, "knight", false), 6, 7, this);
board[7][7] = new Square(new Piece(this, "rook", false), 7, 7, this);
board[0][6] = new Square(new Piece(this, "pawn", false), 0, 6, this);
board[1][6] = new Square(new Piece(this, "pawn", false), 1, 6, this);
board[2][6] = new Square(new Piece(this, "pawn", false), 2, 6, this);
board[3][6] = new Square(new Piece(this, "pawn", false), 3, 6, this);
board[4][6] = new Square(new Piece(this, "pawn", false), 4, 6, this);
board[5][6] = new Square(new Piece(this, "pawn", false), 5, 6, this);
board[6][6] = new Square(new Piece(this, "pawn", false), 6, 6, this);
board[7][6] = new Square(new Piece(this, "pawn", false), 7, 6, this);
//white is for making the squares black or white.
var white: Boolean = true;
for (var y1:Number = 0; y1 < 8; y1++ , white = !white)
{
for (var x1:Number = 0; x1 < 8; x1++ , white = !white)
{
//creatings squares for all the squares that do not have pieces initially
if (board[x1][y1] == null )
board[x1][y1] = new Square(null, x1, y1, this);
//Drawing all the pictures and adding them to the board. This is so messy...
board[x1][y1].addToBoard(white);
//Assigning mouse events
//event:clickedPieceEvent = new clickedPieceEvent();
board[x1][y1].addEventListener(MouseEvent.CLICK, onClick);
}
}
}
public function onClick(ev:MouseEvent): void
{
var x:Number;
var y:Number;
if (ev.target instanceof Square)
{
x = ev.currentTarget.xS;
y = ev.currentTarget.yS;
}
//If there's a piece that is clicked.
if (board[x][y].piece != null)
{
//If an ally piece is clicked,
if (game.currentPlayer().white && board[x][y].piece.isWhite)
{
selected = board[x][y];
trace(selected.name);
}
}
//Moving to an empty spot
if (board[x][y].piece == null && selected != null)
{
selected.moveToSquare(board[x][y]);
//Switch players
game.playerOne.active = !game.playerOne.active;
game.playerTwo.active = !game.playerTwo.active;
}
//Kill enemy
if (board[x][y].piece != null && selected.piece != null)
{
if (board[x][y].piece.isWhite && !selected.piece.isWhite)
{
selected.moveToSquare(board[x][y]);
//Switch players
game.playerOne.active = !game.playerOne.active;
game.playerTwo.active = !game.playerTwo.active;
}
}
//Deselecting a piece
if (board[x][y] == selected)
{
selected = null;
}
}
}
Here's my square class:
public class Square extends Sprite
{
var piece:Piece;
//white = true. black = false.
var color:Boolean;
var xS:Number;
var yS:Number;
var board:Board;
public function Square(piece:Piece, x1:Number, y1:Number, board:Board)
{
this.board = board;
this.piece = piece;
this.xS = x1;
this.yS = y1;
this.x = 50*xS;
this.y = 50 * yS;
//trace(x1);
// adding displayobject to the display list
}
function addToBoard(color:Boolean):void
{
//if color == white
if (color == true)
this.graphics.beginFill( 0x995500 , 1 );
else
this.graphics.beginFill( 0xFFDD11 , 1 );
//making the square
this.graphics.drawRect(0, 0, 50, 50);
if (piece != null)
addChild(this.piece.draw());
board.addChild(this);
}
function moveToSquare(square:Square)
{
//moving to an empty space
if (square == null)
{
square.piece = this.piece;
square.addChild(square.piece.draw() );
this.removeChild(this.piece);
this.piece = null;
}
//moving to a space where you capture a piece
else
{
//adding the captured piece to the players stash.
board.game.currentPlayer().captured.push(square.pi ece);
square.removeChild(square.piece);
square.piece = this.piece;
this.removeChild(this.piece);
this.piece = null;
}
}
}
Sorry if it's a bit messy.
Obvious errors in your code:
Board class:
1. You use squares as event dispachers, not the board, which is what I wrote. If you use squares as event dispatchers, you DO NOT NEED to check whether event target is a Square. Squares (and any other display object, for that matter) only dispatch events when either they or their descendants in the display list are event targets. Since your squares will probably not contain any advanced event-dispatching children, you can safely ignore checking whether "e.target" is a Square.
2. I don't know why you have "currentTarget" when assigning "x" and "y" variables, but "currentTarget" indicates the object CURRENTLY processing the event, in this case I believe the board. Board does not have "x" and "y" properties, Squares do. The Square object you are trying to find is "e.target". If you REALLY still want to make sure you are dealing with the correct object, by all means, ignore .1 and check whether "e.target" is a Square.
3. If you do need to check whether "e.target" is a Square, and you are afraid that onClick is called for other type of objects (which it will if you handle events during "capture" or "bubble" phase), you have to "return" in case they are not. You, however, proceed with game logic right after checking "e.target" class, regardless of the outcome of your check.
Cannot see any useful errors in your Square class. Who knows, if you fix the above, it may work. Good luck! :-)
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.