Looping Cubes & Adding Material (Away3D) - actionscript-3

I'm trying to create a loop of cubes and apply a ColorMaterial to the surface. The main actionscript class has the following method for creating the loop. There is an external class file called Building which is responsible for the shape and ColorMaterial. Unfortunately, I seem to be doing something wrong. Flash Builder is not showing any warnings or errors. But when I run a test, all I get is black screen.
private function buildCity():void
{
var citySize:int = 1800;
var buildingSize:int = 100;
var roadSize:int = 50;
// Loop across in the x direction and again in the z direction
for(var cityX:int=citySize/2;cityX<citySize/2;cityX+=buildingSize+roadSize)
{
for(var cityZ:int=citySize/2;cityZ<citySize/2;cityZ+=buildingSize+roadSize)
{
// Create buildings
var building:Building = new Building();
// Position it
building.x = cityX;
building.z = cityZ;
// Add to the scene
view.scene.addChild(building);
}
}
}
The Building class responsible for the shape and material
package
{
import away3d.entities.Mesh;
import away3d.materials.ColorMaterial;
import away3d.primitives.CubeGeometry;
public class Building extends Mesh
{
public function Building()
{
super(new CubeGeometry(50,100,50));
// Make a material
material = new ColorMaterial(Math.random()*0xFFFFFF);
// Offset the y position based on height
y = 50;
}
}
}

Check your loop parameters. For example, in your code above, you set cityX to citySize / 2, then let it iterate while cityX < citySize / 2.
Since cityX >= citySize / 2 from the start, the loop is never executed.
The same goes for the inner loop.

Related

Why am I unable to access the methods of an object via is ObjectContainer

first of all, i'm not a native english speaker but, still, i'll try my best to be understandable and as clear as possible.
So, in my programming class, I need to make a Tile based game (like zelda, for exemple) with animate cc (flash). On a map, I want to make a dance floor with tiles that changes on the rhythm of a music. these tiles are movieclip with two frame, one white and one red.
This is how the tiles are generated:
private function createGrid(): void {
grid = new MovieClip();
addChild(grid);
for (var r: int = 0; r < nbRow; r++) {
for (var c: int = 0; c < nbCol; c++) {
var t: Tiles = new Tiles();
t.x = t.width * c;
t.y = t.height * r;
grid.addChild(t);
}
}
grid.x = 15; //center the grid on x
grid.y = 35; //center the grid on y
}
This is the Tiles Class :
package {
import flash.display.MovieClip;
import flash.events.*;
public class Tiles extends MovieClip {
private var rand:int;
public function Tiles() {
// constructor code
getTiles();
}
public function getTiles():void {
random();
setColor();
}
private function random() : void{
rand = Math.floor(Math.random()*100)+1;
}
private function setColor() : void{
if(rand<=30){
gotoAndStop(8); //red frame
}else{
gotoAndStop(7); //white frame
}
}
}
}
createGrid() place the tiles as soon as the map is placed on the stage and stock every tiles in the MovieClip grid. Now, I want the tiles to change randomly between red and white on the beat of a streamed music (and keep the ratio of 30% red tiles and 70% white tiles)
var s: Sound = new Sound();
var sc: SoundChannel;
s.load(new URLRequest("GameSong_mixdown.mp3"));
sc = s.play(0, 1000);
I know i need the leftpeek properties of my soundchannel to achieve that but,for now, I do my test with a button that trigger this function:
private function setTiles(e: Event): void {
// loop through all child element of a movieclip
for (var i: int = 0; i < grid.numChildren; i++) {
grid.getChildAt(i).getTiles();
}
}
Right now, the problem is : I'm unable to acces my Tiles method. I did a trace on grid,getChildAt(i), and saw all instances of my tiles in the console. So, i know for sure that every instances of my tiles are stored in grid. But, I don't know why, grid.getChildAt(i).getTiles(); doesn't work (and every other method from Tiles). The error message is: Call to a possibly udefined method getTiles through a reference with static type flash.display:DisplayObject
Does someone know what i'm doing wrong ?
ps: I translated all my class name, var name, etc from french to
english to make the code clearer.
Your mistake is that getChildAt(...) method has a return type of DisplayObject which is neither dynamic (will not let you access random properties) nor it have DisplayObject.getTiles() method.
All you need is to tell the program that this object is actually of Tiles class:
private function setTiles(e:Event):void
{
// loop through all child element of a movieclip
for (var i: int = 0; i < grid.numChildren; i++)
{
// Cast display objects to Tiles class.
var aTiles:Tiles = grid.getChildAt(i) as Tiles;
// Call the method.
aTiles.getTiles();
}
}

How to make a Grid, draw a shape in any of those cells and connect them together?

I have a very unique question regarding to my project
I have made a Grid including 25x15 cells using 3 classes:
First class named Tile.as and make cells for me:
package
{
import flash.display.Shape;
import flash.display.Sprite;
public class Tile extends Sprite
{
static const TILE_SIZE:int = 30;
public function Tile()
{
var tile:Shape=new Shape();
tile.graphics.lineStyle(3, 0x000000);
tile.graphics.drawRect(TILE_SIZE / 2, TILE_SIZE / 2, TILE_SIZE, TILE_SIZE);
this.addChild(tile);
}
}
}
The next class named Grid.as to integrate all Tile together:
package
{
import flash.display.Sprite;
public class Grid extends Sprite
{
static const GRID_SIZE:int = 25;
private var tileList:Vector.<Tile>;
public function Grid()
{
tileList = new Vector.<Tile>;
for (var v:int = 0; v < GRID_SIZE; v++)
{
for (var z:int = 0; z < GRID_SIZE-15; z++)
{
var tile:Tile = new Tile();
tile.x = v*Tile.TILE_SIZE;
tile.y = z*Tile.TILE_SIZE;
tileList.push(tile);
this.addChild(tile);
tile = null;
}
}
}
}
}
And then I showed Grid in my Main.as class and show it in the out put:
public class Main extends Sprite
{
//grid
private var grid:Grid;
//
public function Main()
{
//show the grid
grid = new Grid();
grid.x = 10;
grid.y = 10;
this.addChild(grid);
//
}
}
This is what I can see now:
My question is that i want to add two objects in this grid. For example:
object A will be located in one cell (Tile)
object B will be located in another cell (Tile)
and then I want to connect these 2 objects together by highlighting the dimensions of the cells!
this is an example of what I need to have:
Please ask me, if there is more explanation need to added!
And if I am going through the wrong way, please make me correct!
Thanks in advance!
If its about Path finding
i'm not sure if this question was about path finding!
but according #NealDavis comment:
i post a library for this possibility. however its a grid based path finding and also drawing, even with a fully clear grid.
from dauntless :
According to WikiPedia, A* (pronounced A Star) is
a best-first, graph search algorithm that finds the least-cost path
from a given initial node to one goal node (out of one or more
possible goals).
Here is a Live Demo
References to this library
documentation
source code

Actionsript 3.0 control multiple Instances of a class using a single function

Hey I'm new to Flash AS 3.0 and I am having trouble with creating instances of classes and want to Control them using a single function for all of them.
import flash.display.MovieClip;
import flash.events.*;
stage.addEventListener (KeyboardEvent.KEY_DOWN, movestuff);
var newsymbol:MovieClip;
newsymbol = new Symbol1;
addChild(newsymbol);
newsymbol.x = 200
newsymbol.y = 200
addChild(newsymbol);
function movestuff (event:KeyboardEvent):void
{
newsymbol.x + 100
}
Symbol1 is a class from the library that I am trying to move, and I want to add multiple instances of it but control all of them using the function movestuff
Keep the instances in an array:
var penguinArray:Array = [];
function addPenguin(){
var newPenguin:Penguin = new Penguin();
//do stuff
penguinArray.push(newPenguin);
}
function moveStuff(){
for(var i in penguinArray){
penguinArray[i].x += 10;
}
}
Is your movement that uniform between all of them (do you want to move them all by the same x and y)? If so, put them all inside one parent movie clip and only move that.

AS3 - Dynamically re-populate a series of textFields held within a group of MovieClips

I’ve come across a problematic issue with some functionality I’m attempting to develop in ActionScript3 on the Flash Professional CS5 platform and was wondering if anybody could point me in the right direction with it?
Background
Within my ActionScript Class, I have written a MouseEvent function which dynamically adds multiple instances of the same MovieClip (user_shape) on to the stage in the formation of a shape that the user has designed in an earlier stage of the program.
This shape effect is achieved through a For Loop that loops through the entire length of a Multi-Dimensional Boolean based array looking for an instance of true (determined by the user’s actions earlier) and then adding a MovieClip to the stage if this is the case.
Each group of MovieClips added with a single click, while always having the same instance name (user_shape), is always assigned a unique ID, which I've set up by including a numerical variable that increments up by 1 each time I add the batch of 'user_shape' MovieClips through left click to the stage.
The user can pick from up to eight different colours to assign to their shape (via selection boxes) before adding it to the stage. For each of these eight colours I have added a numerical variable (shapeCounterBlue, shapeCounterRed etc.) which basically counts ++ every time I add a shape of a certain colour to the stage and likewise it counts -- if I chose to remove a shape.
As a shape is added through my main function I attach a dynamic textField to each MovieClip and populate it with the variable counter number for the particular colour I have selected (see image below).
Problem
OK, so here is my issue. I need my unique number (displayed in white) for each coloured shape to dynamically re-populate and update when I remove a shape from the stage. As you can see in the image I’ve attached, if I were to remove the second blue shape, my third blue shape’s numbers would need to revert from 3 to 2.
Likewise if I had six red shapes on the stage and I decided to remove the third one, then shapes 4,5,6 (before 3 is deleted), would need to have their numbers changed to 3,4,5 respectively.
Or I could have four green shapes and remove the first shape; this would mean that shapes 2,3,4 would actually need to change to be 1,2,3.
You get the idea. But does anybody know how I could achieve this?
My problem has further been hampered by the fact that the textFields for each MovieClip are added dynamically through my For Loop to the user_shape Child. This means that within my AS class, I haven’t been able to publicly declare these textFields and access the values within them, as they only exist in the For Loop used in my add shape function and no where else.
Many thanks in advance.
as to the targeting dynamically created text fields. In your loop assign a name that you can later access.
for(i:int=0;i<myArray.length;i++){
var txt:TextField = new TextField();
txt.name = "txt_" + i;
this.addChild(txt);
}
Then to access your textfields outside the loop target them like this:
var targetTxt:TextField = this.getChildByName("txt_10");
UPDATE
Ok so I had some time and went ahead and solved your entire problem
(Download Source FLA/AS files)
Ok so there are some MCs in the library that I call in my code. I created a Box MC that has a label textfield, a border, and a background MC that I can target to color.
I created a countColors() that loops over all the boxes once you have click on one (triggered from a mouseEvent within each box). It counts the different colors totals in an array and then sends a custom event to let all the boxes know they can fetch the color totals to update their labels.
I hope this helps.
main.as
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
public class main extends MovieClip {
public static var ROOT:MovieClip;
public var totalBoxes:int = 100;
public var boxContainer:Sprite;
public static var colorArray:Array = [0xFF0000, 0x0000FF, 0x00FF00];
public static var colorCount:Array = [0,0,0];
public static var currentColor = 0;
public function main() {
// set ref to this
ROOT = this; // so I can get back to it from the boxes
// color selection
redBtn.addEventListener(MouseEvent.CLICK, chooseColor);
blueBtn.addEventListener(MouseEvent.CLICK, chooseColor);
greenBtn.addEventListener(MouseEvent.CLICK, chooseColor);
// add box container to stage
boxContainer = new Sprite();
boxContainer.x = boxContainer.y = 10;
this.addChild(boxContainer);
var row:int=0;
var col:int=0;
for(var i:int=0; i < totalBoxes; i++){
var box:Box = new Box();
box.x = col * box.width;
box.y = row * box.height;
box.name = "box_" + i;
box.ID = i;
box.updateDisplay();
boxContainer.addChild(box);
if(col < 9){
col++;
}else{
col = 0;
row++;
}
}
}
private function chooseColor(e:MouseEvent):void
{
var btn:MovieClip = e.currentTarget as MovieClip;
switch(btn.name)
{
case "redBtn":
currentColor=0;
break;
case "blueBtn":
currentColor=1;
break;
case "greenBtn":
currentColor=2;
break;
}
// move currentColorArrow
currentColorArrow.x = btn.x;
}
public function countColors():void
{
colorCount = [0,0,0]; // reset array
for(var i:int=0; i < totalBoxes; i++){
var box:Box = boxContainer.getChildByName("box_" + i) as Box;
if(box.colorID > -1)
{
colorCount[ box.colorID ]++;
}
}
// send custom event that boxes are listening for
this.dispatchEvent(new Event("ColorCountUpdated"));
}
}
}
Box.as
package {
import flash.display.MovieClip;
import flash.geom.ColorTransform;
import flash.events.MouseEvent;
import flash.events.Event;
public class Box extends MovieClip {
public var ID:int;
public var colorID:int = -1;
private var active:Boolean = false;
private var bgColor:Number = 0xEFEFEF;
public function Box() {
this.addEventListener(MouseEvent.CLICK, selectBox);
main.ROOT.addEventListener("ColorCountUpdated", updateCount); // listen to root for custom event to update display
}
public function updateDisplay() {
if(active == false){
boxLabel.htmlText = "<font color='#000000'>"+ ID +"</font>";
}else{
boxLabel.htmlText = "<font color='#FFFFFF'>"+ main.colorCount[colorID] +"</font>";
}
var myColorTransform = new ColorTransform();
myColorTransform.color = bgColor;
boxBG.transform.colorTransform = myColorTransform;
}
private function selectBox(e:MouseEvent):void
{
// set bgColor
if(active == false){
bgColor = main.colorArray[main.currentColor];
colorID = main.currentColor;
}else{
bgColor = 0xEFEFEF;
colorID = -1;
}
// set active state
active = !active // toggle true/false
main.ROOT.countColors();
}
private function updateCount(e:Event):void
{
updateDisplay();
}
}
}

Papervision3D cube face orientation

I have a question about Papervision3D, or perhaps bitmapData, I am unsure where the problem is. I have constructed a program that takes 4 banners and splits them into pieces and then applies those pieces to cubes so that I can make a banner rotator. So after I run my program I have 10 cubes with a piece of a banner on 4 faces(front, top, back, bottom) of each cube. The problem is that some of the faces are oriented incorrectly(spun 180 degrees). Is there a way in Papervision3D to spin a cube face? The other place I think the problem may be is when I create the bitmapData that will be applied to the cube faces. Is there some way to explicitly define orientation during bitmapData creation? Any help or ideas would be greatly appreciated. Thanks!
-------Edit----------
Here is the code for my CubeMaker.as class. This is the class that takes the image pieces and applies them to the cubes.
package {
import away3d.events.MaterialEvent;
import away3d.materials.BitmapMaterial;
import away3d.materials.ColorMaterial;
import away3d.materials.TransformBitmapMaterial;
import away3d.primitives.Cube;
import away3d.primitives.data.CubeMaterialsData;
import CubeEvent;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
public class CubeMaker extends Sprite {
private var _colorMaterial:ColorMaterial = new ColorMaterial(0x000000);
private var _dcRef;
private var _banners:Array;
private var _cubeArray:Array = [];
private var _cubeCoung:int = 0;
private var _numberOfPieces:int;
private var _width:Number;
private var _depth:Number;
private var _height:Number;
public function CubeMaker(banners:Array, numberOfPieces:int) {
_dcRef = DocumentClass._base;
_banners = banners;
_numberOfPieces = numberOfPieces;
}
public function makeCubes() {
//loop through the cubes
for (var i = 0; i < _numberOfPieces; i++) {
var faceBitmapArray:Array;
//fill array with four faces for current cube
faceBitmapArray = fillFace(i);
//get width and height from a piece instance
var width:Number;
var height:Number;
var tempArray:Array;
tempArray = _banners[0];
_width = tempArray[0].width;
_height = tempArray[0].height;
_depth = tempArray[0].height;
//create four materials from bitmapData
var myFront:TransformBitmapMaterial = new TransformBitmapMaterial(faceBitmapArray[0], {rotation:0} );
var myTop:TransformBitmapMaterial = new TransformBitmapMaterial(faceBitmapArray[1], {rotation:0.5} );
var myBack:TransformBitmapMaterial = new TransformBitmapMaterial(faceBitmapArray[2], {rotation:0} );
var myBottom:TransformBitmapMaterial = new TransformBitmapMaterial(faceBitmapArray[3], {rotation:0} );
//create two materians from color
var myLeft:ColorMaterial = new ColorMaterial(0x000000);
var myRight:ColorMaterial = new ColorMaterial(0x000000);
//create a CubeMatrialsData from the materials created above
var myMaterials:CubeMaterialsData = new CubeMaterialsData( { front:myFront, back:myBack, top:myTop, bottom:myBottom, left:myLeft, right:myRight} );
//listen for material change
myMaterials.addOnMaterialChange(materialChanged);
//create a new cube with the CubeMaterialsData created earlier
var _cube = new Cube({width:_width, height:_height, depth:_depth, cubeMaterials:myMaterials});
//the created cube is put into the _cubeArray
_cubeArray[i] = _cube;
if (i == (_numberOfPieces - 1)) cubesMade();
}
}
private function fillFace(i:int):Array {
var faceBitmapArray:Array = [];
for (var j = 0; j < 4; j++) {
//tempBannerArray filled with one banner in pieces
var tempBannerArray:Array = _banners[j];
//batmapData created and sized to current banner piece
var bitmapData:BitmapData = new BitmapData(tempBannerArray[i].width, tempBannerArray[i].height);
//bitmapData filled with current banner piece bitmap data
bitmapData = tempBannerArray[i].bitmapData;
bitmapData.lock();
//array is filled with bitmap data
faceBitmapArray[j] = bitmapData;
}
return faceBitmapArray;
}
private function cubesMade() {
//dispatch event to notify of cube making completion
dispatchEvent(new CubeEvent(CubeEvent.CUBES_MADE, _cubeArray.length));
}
private function materialChanged(e:MaterialEvent):void {
trace("Warning! Warning! Material changed!");
}
public function get cubes():Array {
return _cubeArray;
}
public function get cubeWidth():Number {
return _width;
}
public function get cubeHeight():Number {
return _height;
}
public function get cubeDepth():Number {
return _depth;
}
}
}
Preface: Papervision3D is close to unsupported / closed as a library, so I highly recommend using Away3D or another actionscript 3D library. Though the work done on PV3D was groundbreaking and incredible from a flash perspective so if you're looking to build a 3D experience with it, it's quite good. Just know from the get-go that future dev + support are unlikely.
Preface aside, take a look at the "Cube" primitive class in the library. You can create Materials and attach them to the MaterialsList instance that will be added to the cube instance. Assuming you're using BitmapMaterial, it has a "rotation" property, that you can set. Just determine which materials are upside-down and make their rotation = 180. Pros: quick; Cons: hard-coded.
The other option is to hit the problem on the "asset" end and flip your images. Pros: quick; Cons: non-scalable or puts the issue on the designer.
The best option, when loading the data / assets, is to have a "rotate" property that you can use to set which images should be flipped. It's a cube, so like Ender says, up is relative.