Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411649 Posts in 69395 Topics- by 58451 Members - Latest Member: Monkey Nuts

May 15, 2024, 10:11:50 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Attaching Tile Sprites
Pages: [1]
Print
Author Topic: Attaching Tile Sprites  (Read 1997 times)
Craig Stern
Level 10
*****


I'm not actually all that stern.


View Profile WWW
« on: June 19, 2010, 07:05:52 AM »

I'm working on the tile-based battlefield portion of a turn-based strategy engine in AS3. I've gotten Flash to lay down tile sprites according to the values in an array fairly easily, but the method I'm using is clunky and inelegant. I'm assuming that there is  a better way to do this, and I just haven't discovered it yet. Here is my current code--this first bit is in a class called Battlefield:

Code:
public class Battlefield extends MovieClip {

public function Battlefield (targetArray , columns , tileWidth , tileHeight) {

var rows:int = targetArray.length;

for ( var yInt:int = 0 ; yInt < rows ; yInt++ ) {
for ( var xInt:int = 0 ; xInt < columns ; xInt++ ) {
//ADD TILES
var myTile:Tile = new Tile (targetArray[yInt][xInt]);
myTile.name = "tile" + yInt + "." + xInt;
addChild(myTile);

myTile.x = xInt * tileWidth;
myTile.y = yInt * tileHeight;
myTile.rotation = 0;
}
}

}

}

This second bit is in the class Tile (Tile, in the Flash IDE, is just an empty Sprite--the actual graphics for each type of terrain are separate Sprites with the names Tile1, Tile2, Tile3, and Tile4):

Code:
public class Tile extends MovieClip {

public function Tile (tileType) {

var myTileSprite;

if (tileType == 1) {
myTileSprite = new Tile1();
}
else if (tileType == 2) {
myTileSprite = new Tile2();
}
else if (tileType == 3) {
myTileSprite = new Tile3();
}
else if (tileType == 4) {
myTileSprite = new Tile4();
}

addChild(myTileSprite);

}

}

This works fine for now, but I can tell it's going to become onerous once I start adding significant numbers of different tiles to the game. In AS2, it would have been simple to just define a variable inside the for loop in Battlefield by appending the current array value to the end of a string, then attaching that variable to the stage via attachMovie. I haven't found a way to make this work in AS3, unfortunately. Any pointers?
Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #1 on: June 19, 2010, 07:36:07 AM »

Ok, two things:

1) Instead of using sprite.name, it is usually easier to keep the sprite objects themselves in an array you can access. No mucking about with getChildByName and string manipulation.

2)
Code:
var tileClasses:Array = [Tile1, Tile2, Tile3, Tile4];
var tileClass:Class = tileClasses[tileType-1] as Class;
addChild(new tileClass());
Logged
Craig Stern
Level 10
*****


I'm not actually all that stern.


View Profile WWW
« Reply #2 on: June 19, 2010, 09:31:11 AM »

Awesome, thanks! Smiley
Logged

Triplefox
Level 9
****



View Profile WWW
« Reply #3 on: June 19, 2010, 09:29:38 PM »

Re: Tile-image mapping methods, the array suggested is the simplest way to manage it but if you want something with a more efficient production process, you can also write a code generation script that does this mapping for you. Ideally it should be done in a way so that the index of each tile remains stable across all builds, regardless of what gets added. (If you're using the classic bitmaps and regular-sized-tiles strategy, the indexes can also be made stable without any code generation by dumping all tiles in one image and slicing them up at runtime in a fixed order.)

If your map is going to contain a lot of tiles you may want to use draw() to put them on a single BitmapData. When you add nodes to the Flash scenegraph it adds some overhead on all mouse operations, because Flash will check every node for click and rollover events, and the last time I tested it, the performance loss occurred even if you disabled input on those nodes. With a single BitmapData, it's pretty easy to use division to find tile locations instead(the exception being if you have an odd isometric projection, hexes, or other unusual things going on), and scrolling will be more efficient and stable as well.
Logged

Craig Stern
Level 10
*****


I'm not actually all that stern.


View Profile WWW
« Reply #4 on: June 23, 2010, 04:26:37 PM »

Hm. That makes sense in an abstract way, but I haven't the slightest clue how to implement what you just said. I'll probably need to look into that more if I decide to make a platformer, or other action game. This is for something turn-based, so I'm not too worried about tweaking for performance at the moment. Wink

So, I have a new question. I tried using Boris's technique for code to attach characters to the battlefield, and it's throwing back Error #1007: Instantiation attempted on a non-constructor. Here is how I have it structured: Battlefield is an empty movieclip that contains all the Tile sprites. After I add the tiles, I want to add Characters to it as well. Right now I'm starting small, just trying to add the Hero. First I attach Character to the battlefield in my document class. Then I add the sprite for the particular type of character I want inside Character:

Code:
public class Character extends Sprite {

public function Character (charElement , charType , charName , charSpeed , charMove , charHealth , charDef , charStr , charIceRes , charAirRes , charFireRes , charLightRes , charDarkRes , charPriority) {

var charClass:Class = charType as Class;
addChild(new charClass());
}
}

This gives me Error #1007. This, on the other hand, works great, although it suffers from the obvious disadvantage that it only works on a single Class:

Code:
public class Character extends Sprite {

public function Character (charElement , charType , charName , charSpeed , charMove , charHealth , charDef , charStr , charIceRes , charAirRes , charFireRes , charLightRes , charDarkRes , charPriority) {

var myHero:Hero = new Hero();
addChild(new myHero);
}
}

How can I fix this?
Logged

agj
Level 10
*****



View Profile WWW
« Reply #5 on: June 23, 2010, 06:17:06 PM »

The obvious question would be: are you sure that you're passing a class as the charType parameter?

I suggest you type your parameters so that you don't get these kinds of error. So:

Code:
public class Character extends Sprite {

public function Character (charElement:String, charType:Class, charName:String, charSpeed:Number, charMove:Number, charHealth:Number, charDef:Number, charStr:Number, charIceRes:Number, charAirRes:Number, charFireRes:Number, charLightRes:Number, charDarkRes:Number, charPriority:Number) {

addChild(new charType());
}
}

But if charType is not a class reference, but a string, then you need to use getDefinitionByName, like so:

Code:
addChild(new getDefinitionByName(charType)());
Logged

Craig Stern
Level 10
*****


I'm not actually all that stern.


View Profile WWW
« Reply #6 on: June 23, 2010, 06:37:51 PM »

Here's the code from the document class that attaches the Character and feeds it arguments:

Code:
//the array containing all the different characters and their values
charClasses[charClasses.length] = [heroElement , "Hero" , heroName , heroSpeed , heroMove , heroHealth , heroDef , heroStr , heroIceRes , heroAirRes , heroFireRes , heroLightRes , heroDarkRes , 0 , 0 , 0 , heroPriority];
charClasses[charClasses.length] = ["Light" , "Minion" , "Bright Lancer" , 5 , "Land" , 12 , 4 , 4 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0];
charClasses[charClasses.length] = ["Light" , "Minion" , "Guardian Force" , 5 , "Land" , 12 , 4 , 4 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0];

//etc.

addCharacter(0); //add Hero using the addCharacter function

//ADD CHARACTER
function addCharacter (charID) {
var myCharacter:Character = new Character(charClasses[charID][0] , charClasses[charID][1] , charClasses[charID][2] , charClasses[charID][3] , charClasses[charID][4] , charClasses[charID][5] , charClasses[charID][6] , charClasses[charID][7] , charClasses[charID][8] , charClasses[charID][9] , charClasses[charID][10] , charClasses[charID][11] , charClasses[charID][12] , charClasses[charID][16] );
battlefieldMCArray[0].addChild(myCharacter); //add new Character as a Child of Battlefield
characterMCArray.push(myCharacter); //add new Character MC to the array for reference

So charType is a String. Is it possible to type it as a Class in the array?

EDIT: Interesting. If I use Hero instead of "Hero", Flash seems to recognize it as the Hero class. I'm pleasantly surprised that that worked.
« Last Edit: June 23, 2010, 07:54:39 PM by Craig Stern » Logged

agj
Level 10
*****



View Profile WWW
« Reply #7 on: June 23, 2010, 06:51:15 PM »

Yes. Just remove the quotes.
Logged

Craig Stern
Level 10
*****


I'm not actually all that stern.


View Profile WWW
« Reply #8 on: June 23, 2010, 08:10:42 PM »

Lovely, thanks for the help. Smiley
Logged

Craig Stern
Level 10
*****


I'm not actually all that stern.


View Profile WWW
« Reply #9 on: July 09, 2010, 08:53:10 AM »

All right Flash gurus, here's a new question. I'm working on an adventure game engine that attaches monsters to each room using an array. The code is similar to the Tile code above. In the document class:

Code:
private function addMonsters () {
for ( i = 0 ; i < roomObjs.length ; i++ ) { //Y - height
for ( j = 0 ; j < roomObjs[i].length ; j++ ) { //X - width
if (roomObjs[i][j] > 0) { //if there isn't just nothing there
var newMonster:Monster = new Monster (roomObjs[i][j]);
addChild(newMonster);
newMonster.x = j * tileSize;
newMonster.y = i * tileSize;

char[char.length] = newMonster;
}
}
}
}

And in the Monster class, code that adds the appropriate monster as a child of Monster:

Code:
public function Monster (monsterType) {

Type = monsterType;

var monsterClasses:Array = [Slime_Green , Slime_Blue, Slime_Red, Bat, Snake];
var monsterClass:Class = monsterClasses[monsterType - 1] as Class;
addChild(new monsterClass());

var monsterObj:Object = monsterClass as Object;

monsterObj.x -= monsterObj.width / 2;
monsterObj.y -= monsterObj.height / 2;

}

It's those last few lines in the second snippet of code that are giving me trouble. I want them to center the movieClip associated with monsterClass in the movieclip associated with Monster, but the "as Class" trick doesn't seem to work the other way when I try "as Object." I also tried "as MovieClip" and "as Sprite", but those just threw up compile-time errors. Any pointers?
Logged

st33d
Guest
« Reply #10 on: July 09, 2010, 09:05:06 AM »

Code:
var monsterObj:Sprite = new monsterClass();
monsterObj.x -= monsterObj.width * 0.5;
monsterObj.y -= monsterObj.height * 0.5;

You're confusing a class with an object. A class is the cookie cutter, but won't tell you how big the cookie is. For that you need the cookie.

And avoid using the division sign in favour of fractions where you can. Computers are much slower at dividing numbers than multiplying them.
Logged
Craig Stern
Level 10
*****


I'm not actually all that stern.


View Profile WWW
« Reply #11 on: July 10, 2010, 04:28:00 PM »

Thanks--that's very helpful! Smiley Here's the new (working) code, for anyone reading along:

Code:
public function Monster (monsterType) {

var monsterClasses:Array = [Slime_Green , Slime_Blue, Slime_Red, Bat, Snake];
var monsterClass:Class = monsterClasses[monsterType - 1] as Class;
var monsterObj:Sprite = new monsterClass();
addChild(monsterObj);

monsterObj.x -= monsterObj.width * 0.5;
monsterObj.y -= monsterObj.height * 0.5;

}
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic