Craig Stern
|
|
« on: June 14, 2010, 05:36:22 PM » |
|
This is probably going to sound like a stupid question, but I'm not making much headway trying to figure it out on my own, so I figure I might as well ask. I'm tinkering around, building a card game engine in AS3. In the document class, I've got a function which deals out the cards in the player's deck: function showDeck () { for (i = 0 ; i < playerDeck.length ; i++ ) { //ADD CARD MOVIECLIP var myCard:Card = new Card(); addChild(myCard); myCard.x = 10; myCard.y = 40 + (i * 25); myCard.rotation = 0; myCard.gotoAndStop(playerDeck[i][0]); //make card BG correct color myCard.currCardName = playerDeck[i][2]; //give card correct name
} } You'll note, at the end of that function, some code which tries to pass the correct name of each card from an array to the new card instance. The class Card, in turn, has in its class method code which adds the title of the card to each card when it's created: //ADD CARD NAME TEXT var cardNameText:TextField = new TextField();
cardNameText.text = currCardName; addChild(cardNameText); cardNameText.x = 5; cardNameText.y = 5; cardNameText.width = 125; cardNameText.height = 30; cardNameText.border = false; cardNameText.selectable = false; Or at least, that should be what it does. Unfortunately, I don't seem to be passing currCardName from my document class to the Card class correctly. I'm 98% sure that I'm doing something stupid, but as a newcomer to OOP, I'm not quite sure what it is. Any pointers?
|
|
|
Logged
|
|
|
|
Matt Thorson
|
|
« Reply #1 on: June 14, 2010, 05:42:30 PM » |
|
When is the second block of code executed? If it's in Card's constructor, that's your problem. Right now you're constructing the Card object, at which point the text is set to the title string (which is probably some default value right now because it hasn't been set yet), then you're setting the title string. What you'd want to do is add a "name" parameter to Card's constructor so you can create the Card object like: var myCard:Card = new Card(playerDeck[i][2]);
|
|
|
Logged
|
|
|
|
Craig Stern
|
|
« Reply #2 on: June 14, 2010, 05:57:40 PM » |
|
If it's in Card's constructor, that's your problem. Right now you're constructing the Card object, at which point the text is set to the title string (which is probably some default value right now because it hasn't been set yet), then you're setting the title string. Okay, that makes sense. What you'd want to do is add a "name" parameter to Card's constructor so you can create the Card object like: var myCard:Card = new Card(playerDeck[i][2]); You lost me on this part. What would this do, exactly? Never mind, figured it out. Brilliant! Thanks for the help!
|
|
« Last Edit: June 14, 2010, 07:00:31 PM by Craig Stern »
|
Logged
|
|
|
|
BorisTheBrave
|
|
« Reply #3 on: June 15, 2010, 02:08:26 AM » |
|
I think you've missed a trick with OO. Is playerDeck purely for loading purposes? If not, wouldn't it make more sense that each player's deck is composed of instances of Card, too? That makes the actual game code a lot simpler, as we don't have to worry about constantly converting between Cards and array format.
|
|
|
Logged
|
|
|
|
Craig Stern
|
|
« Reply #4 on: June 15, 2010, 05:55:19 AM » |
|
Is playerDeck purely for loading purposes? Nope.
|
|
|
Logged
|
|
|
|
Matt Thorson
|
|
« Reply #5 on: June 15, 2010, 10:19:43 AM » |
|
If it's in Card's constructor, that's your problem. Right now you're constructing the Card object, at which point the text is set to the title string (which is probably some default value right now because it hasn't been set yet), then you're setting the title string. Okay, that makes sense. What you'd want to do is add a "name" parameter to Card's constructor so you can create the Card object like: var myCard:Card = new Card(playerDeck[i][2]); You lost me on this part. What would this do, exactly? Never mind, figured it out. Brilliant! Thanks for the help! Glad I could help. When can we play the game?
|
|
|
Logged
|
|
|
|
Craig Stern
|
|
« Reply #6 on: June 15, 2010, 03:17:08 PM » |
|
When can we play the game? There's not much to show just yet, but I'll be sure to post about it when I've got something worth seeing. (Or, you know, when AS3 confounds me again and I need some help. )
|
|
|
Logged
|
|
|
|
agj
|
|
« Reply #7 on: June 15, 2010, 06:05:21 PM » |
|
I have toyed with the idea of creating a system to play any card game, as if it were a real deck (allowing you to have a hand, piles, rows of cards, etc.), online. Is this sort of what you're making? If so, awesome, I don't have to make it myself!
|
|
|
Logged
|
|
|
|
Craig Stern
|
|
« Reply #8 on: June 15, 2010, 07:14:54 PM » |
|
Sorta. I'm basically teaching myself AS3 by creating a turn-based strategy game / collectible card game. My goal is to make it something like a cross between Magic: the Gathering and Shining Force. I'm working on the card engine first--as of now, I've got it so it randomly generates a player deck from an index of all possible cards, then shuffles the deck, then deals a hand of 7 cards to the player, then displays the hand. The cards are all draggable, and are generated from code based on values stored in an array. (I just finished coding it so it displays casting cost symbols on the cards a little while ago.)
|
|
|
Logged
|
|
|
|
Craig Stern
|
|
« Reply #9 on: June 24, 2010, 10:17:45 PM » |
|
I'm working on code to play cards from your hand now, and I'm experiencing sort of the inverse of my original problem: namely, determining the number associated with the card being clicked, and using that pull the card's info from an array (so as to determine casting cost, what type of card it is, etc.) Here is the code in the document class that attaches each card movieclip in the first place: //ADD CARD MOVIECLIP var myCard:Card = new Card(targetArray[i][1] , targetArray[i][2] , targetArray[i][3] , targetArray[i][4] , targetArray[i][5] , targetArray[i][6] , targetArray[i][7] , targetArray[i][8] , targetArray[i][10] , i ); //creates a new instance of Card, referred to by the variable myCard; passes along cardName, cardType myCard.name = "card" + i; addChild(myCard); //adds the myCard movieclip instance as a child of the stage myCard.x = 10; myCard.y = 40 + (i * vertSpacing); if (i > columnMax) { myCard.x += horSpacing; myCard.y -= ((columnMax + 1) * vertSpacing); } myCard.rotation = 0; myCard.gotoAndStop(targetArray[i][0]); cardMCArray.push(myCard); It's that very last argument in the first line of real code there, i, that I am storing in each card like so via the Card class, and which I need to be able to retrieve later: public class Card extends MovieClip { public function Card (cardType , cardName, iceCost , airCost , fireCost , lightCost , darkCost , miscCost , range , cardID) { var ID:int = cardID; My current attempts at determining the ID for each card upon activation involve the following code in the document class: //MAKE DRAGGABLE and DOUBLE-CLICKABLE myCard.doubleClickEnabled = true; addListeners(myCard); function addListeners (card:Card) { if (targetArray == playerHand) { card.addEventListener(MouseEvent.DOUBLE_CLICK, playCard); }
function playCard (event:MouseEvent) { payCastingCost(etherArray); //check to see if player has enough ether to pay casting cost trace(event.target); cardPlayed = event.target.ID; if (castingCostPaid == true) { if (playerHand[cardPlayed][1] == "Minion") { //move card from player's hand to the field addCharacter(cardPlayed); } removeChild(cardMCArray[cardPlayed]); playerHand.splice(cardPlayed , 1); } } The event.target code, when traced, returns [object Card]. Any attempt at accessing the ID property that way gets me Error #1069: Property ID not found on Card and there is no default value. It seems to me that event.target is referring to the class Card, and not to the instance on the stage. How can I work around this problem?
|
|
|
Logged
|
|
|
|
bateleur
|
|
« Reply #10 on: June 24, 2010, 10:30:32 PM » |
|
It seems to me that event.target is referring to the class Card, and not to the instance on the stage. How can I work around this problem? That doesn't sound right. You wouldn't get that error message if that was the problem. I suspect the difficulty is most likely that you're trying to use objects as if they were duck typed. AS3 actually has a proper type system and won't allow this. So, in particular: cardPlayed = event.target.ID; ...is bad, because event.target has type Object even if the specific instance at runtime happens to be an instance of Card. You cannot access 'ID' like this, because it is a field of the class 'Card' and not the class 'Object'. Instead, do either this: cardPlayed = Card(event.target).ID; ...or this... cardPlayed = (event.target as Card).ID; ...which in your case will make no difference. (Generally speaking you use 'as' when the cast could fail. If it does, you then get a null object rather than an Exception.)
|
|
|
Logged
|
|
|
|
Craig Stern
|
|
« Reply #11 on: June 25, 2010, 08:45:12 AM » |
|
Both methods leave me with a compiler error: 1119: Access of possibly undefined property ID through a reference with static type Card.
|
|
|
Logged
|
|
|
|
agj
|
|
« Reply #12 on: June 25, 2010, 09:28:44 AM » |
|
I'll admit that I didn't look very closely at your code, but it seems to me that you're declaring the variable within the constructor function, whereas you need to declare it outside of any function, but within the class declaration, so that it actually belongs to the scope of the class. The 'var' keyword is context-sensitive, so to speak. From within the constructor you can access (and set) that variable by skipping the 'var' keyword.
|
|
|
Logged
|
|
|
|
Sam
|
|
« Reply #13 on: June 25, 2010, 09:44:25 AM » |
|
Whilst you were typing a new reply has been posted.. I am totally repeating what agj just said, sorry! public class Card extends MovieClip { public function Card (cardType , cardName, iceCost , airCost , fireCost , lightCost , darkCost , miscCost , range , cardID) { var ID:int = cardID; } } Your current code declares a variable called ID within the constructor function, which can then only be accessed from within that same function. public class Card extends MovieClip { public var ID:int; public function Card (cardType , cardName, iceCost , airCost , fireCost , lightCost , darkCost , miscCost , range , cardID) { ID = cardID; } } Move the declaration of ID to outside of any function (but within the Card class definition), set it as Public and now that variable can be accessed by stuff outside of the Card class.
|
|
|
Logged
|
|
|
|
Craig Stern
|
|
« Reply #14 on: June 25, 2010, 12:45:49 PM » |
|
Wonderful, thank you! I knew there had to be a way to do that.
|
|
|
Logged
|
|
|
|
PleasingFungus
|
|
« Reply #15 on: June 25, 2010, 01:45:32 PM » |
|
For the record, you actually can emulate duck typing with AS3: foo.bar() #in a duck-typed language translates to This is horrible and morally reprehensible and removes all compile-time type-checking; plus, I strongly suspect that there's a nasty speed penalty for this. But, well. If it comes up.
|
|
|
Logged
|
|
|
|
bateleur
|
|
« Reply #16 on: June 26, 2010, 01:51:17 PM » |
|
This is horrible and morally reprehensible and removes all compile-time type-checking; plus, I strongly suspect that there's a nasty speed penalty for this. But, well. If it comes up. It's also a little bit surprising to me that it works (as indeed it does) since I would have expected () to require an object of (known) type Function. Since foo["bar"] is in general not a function even when it is defined, it seems wrong to me that this construction doesn't at least spit out a warning.
|
|
|
Logged
|
|
|
|
BorisTheBrave
|
|
« Reply #17 on: June 27, 2010, 01:45:48 PM » |
|
Using brackets is nothing special, it's just turning off static typing. You can just as easily do var foo2:* = foo; foo2.bar.
Either way, it is casting foo to a dynamic object (in this case, Object), retrieving the property with name "bar", casting it to Function, and applying it.
I don't know why you call it duck typing, it is exactly like regular scripting languages do it, and with a big it compared with static stuff. If you make all your objects "dynamic", then they behave like regular scripting language objects.
|
|
|
Logged
|
|
|
|
bateleur
|
|
« Reply #18 on: June 28, 2010, 02:49:09 AM » |
|
A dynamic object is just one to which you can add properties at runtime, so there's no necessity for such an object to allow itself to be cast to a Function.
The reason I referred to "duck typing" originally is because Craig Stern appeared to have written code that accessed a property on the basis that it new for sure that it was defined, which in a duck typed language is fine. (And it's not in general fine in AS3, as you know.)
|
|
|
Logged
|
|
|
|
BorisTheBrave
|
|
« Reply #19 on: June 28, 2010, 12:34:47 PM » |
|
A dynamic object is just one to which you can add properties at runtime, so there's no necessity for such an object to allow itself to be cast to a Function.
Right, but then you get the "bar" property. This will be a type "*" as obviously the compiler doesn't know the type. And anything of type "*" can be implicitly cast to anything, including Function.
|
|
|
Logged
|
|
|
|
|