I'm attempting to change the color of several display objects using colorTransform but can't get it working -
private function getChildren(mc:DisplayObjectContainer):Array {
var children:Array = [];
for (var i:int = 0; i < mc.numChildren; i++) {
var child:DisplayObject = mc.getChildAt(i);
if(child.name == "color1"){
children.push(child);
} else if(child.name == "color2"){
children.push(child);
}
if (child is DisplayObjectContainer) {
var childChildren:Array = getChildren((child as DisplayObjectContainer));
children = children.concat(childChildren);
}
}
return children;
}
and in my enter stage event:
var mychildren:Array = getChildren(this.spartan);
for each(var child:DisplayObject in mychildren) {
if(child.name == "color1"){
child.transform.colorTransform = _colorTransform1;
}
trace(child.name);
I've declared the color as _colorTransform1.color = 0xCCFF00
My character subsists of several movieclips that are currently either instances of color1:red or color2:green. As a new programmer I'm wondering if I should have proceeded with another method?
trace(child.name)
if(child.name == "color1"){
trace("found color!")
}
Alright, I kind of feel a little stupid right now because the answer was so darn obvious...
While attempting to change the color of the movieclip I had forgotten that the movieclip itself had not loaded yet. To fix this issue all I had to do was call the movieclip frame BEFORE I changed the color.
Related
I have made simple drag-and-drop color buttons where if user drag the specific buttons, it will detects the color based on the what user drag and apply it to the object where user drop the color into. However, I can't figure it out why the color keep changing to black whenever I chose a button and drag and drop it to the single object in the scene, it will turn black even though I already have define the color of buttons.
How can I solve this?
Here is the code that I am using (I am using this on CS6):
var array_objects:Array = new Array(firstRectangle_mc, secondRectangle_mc, thirdRectangle_mc, fourthRectangle_mc);
var hit_object:Array = new Array();
var color_x:int;
var color_y:int;
addListeners(red_btn, black_btn, yellow_btn);
function addListeners(... objects):void
{
var color:Array = new Array("0xFF0000", "0x000000", "0xFFFF00");
for (var i:int = 0; i < objects.length; i++)
{
var input:TextField = new TextField();
input.text = color[i];
input.visible = false;
objects[i].addChild(input);
objects[i].addEventListener(MouseEvent.MOUSE_DOWN, onColorMouseDown);
objects[i].addEventListener(MouseEvent.MOUSE_UP, onColorMouseUp);
}
}
function onColorMouseDown(e:MouseEvent):void
{
hit_object = [];
color_x = e.currentTarget.x;
color_y = e.currentTarget.y;
e.currentTarget.startDrag();
}
function onColorMouseUp(e:MouseEvent):void
{
e.currentTarget.stopDrag();
for (var i:int = 0; i < array_objects.length; i++)
{
if (e.currentTarget.hitTestObject(array_objects[i]))
{
hit_object.push(array_objects[i]);
}
}
e.currentTarget.x = color_x;
e.currentTarget.y = color_y;
var changeColor:ColorTransform = hit_object[hit_object.length - 1].transform.colorTransform;
changeColor.color = e.currentTarget.text;
hit_object[hit_object.length - 1].transform.colorTransform = changeColor;
}
Here is the link of the demo:
Link
Your answer much appreciated!
Thank you very much
Let's see at this line:
changeColor.color = e.currentTarget.text;
e.currentTarget is a circle. What is e.currentTarget.text? Circle doesn't have a text property. It has a child TextField. So, if you want to get text from TextField you must write:
e.currentTarget.getChildAt(1).text;
Circle have two children: Shape and TextField. So getChildAt(1) = TextField.
You can do it without TextField. See:
for (var i:int = 0; i < objects.length; i++)
{
objects[i].color = color[i];
objects[i].addEventListener(MouseEvent.MOUSE_DOWN, onColorMouseDown);
objects[i].addEventListener(MouseEvent.MOUSE_UP, onColorMouseUp);
}
Circle it's a MovieClip. The MC it's a dynamic class, that means that you can add any property to it. In our case, we add a color property.
Next:
changeColor.color = e.currentTarget.color;
Understand?
In your code I have found a bug:
var changeColor:ColorTransform = hit_object[hit_object.length - 1].transform.colorTransform;
If you stop dragging circle and circle doesn't hitTest any boxes the error appears:
TypeError: Error #1010: A term is undefined and has no properties.
To avoid this, add condition:
if (hit_object.length)
{
var changeColor:ColorTransform = hit_object[hit_object.length - 1].transform.colorTransform;
changeColor.color = e.currentTarget.color;
hit_object[hit_object.length - 1].transform.colorTransform = changeColor;
}
I'm making an AS3 platform game where the player can shoot some bullets.
When the bullet is touching an enemy, the enemy die and the bullet is removed.
I've succeed do to that but now I'd like to remove the bullet if it hit a wall and I can't figure out how to do so.
So far, here's my code for removing the bullet when touching an enemy :
public function checkCollisions() {
// enemies
for(var i:int=enemies.length-1;i>=0;i--) {
if (hero.mc.hitTestObject(enemies[i].mc)) {
// is the hero jumping down onto the enemy?
if (hero.inAir && (hero.dy > 0)) {
enemyDie(i);
} else {
heroDie();
}
}
for (var j:int = 0; j < bulletList.length; j++) // for each bullet in the bulletList
{
if (enemies[i].mc.hitTestObject(bulletList[j]) )
{
trace("Bullet and Enemy are colliding");
enemyDie(i)
bulletList[j].removeSelf();
}
}
}
I've defined my wall and floor like this :
public function examineLevel() {
fixedObjects = new Array();
otherObjects = new Array();
for(var i:int=0;i<this.gamelevel.numChildren;i++) {
var mc = this.gamelevel.getChildAt(i);
// add floors and walls to fixedObjects
if ((mc is Floor) || (mc is Wall)) {
var floorObject:Object = new Object();
floorObject.mc = mc;
floorObject.leftside = mc.x;
floorObject.rightside = mc.x+mc.width;
floorObject.topside = mc.y;
floorObject.bottomside = mc.y+mc.height;
fixedObjects.push(floorObject);
}
}
I've tried to put this in my checkCollisions function but it's not working :
for(var k:int=0;k<fixedObjects.length;k++)
{
if (fixedObjects[k].hitTestObject(bulletList[j]) ){
trace("hit wall");
}
Do you know what do I have to put in order to remove the bullet when it's touching a wall (or floor) ?
Thx
The array fixedObjects holds references to Object instances. However, hitTestObject(obj) is a public function of the DisplayObject class, and the obj parameter needs to be an instance of DisplayObject.
If the code snippet you provided is exactly the same as what you used in your game, there should be runtime error messages generated.
Could you please verify whether this is the cause of failing to detect collision?
I am trying to create a game for kids where they can drag letters on to a stage to make words.
I want to add a 'trash can' where users can drag letters they no longer need to dispose of them. I have created the movie clip but am totally unsure how to make it function using AS3.
I would also like to add a reset button so that the stage reverts to it's original state. Again, I have drawn it up and added the little as3 that I am aware of (to make it a button) but if anyone could assist with how to actually make this happen, I would be grateful.
The files are here: SWF | FLA and the code for the game is as follows:
import flash.display.MovieClip;
for (var i=1; i<27; i++)
{
this["object" + i].addEventListener(MouseEvent.MOUSE_DOWN, onStart);
this["object" + i].addEventListener(MouseEvent.MOUSE_UP, onStop);
}
var sx = 0,sy = 0;
function onStart(e)
{
sx = e.currentTarget.x;
sy = e.currentTarget.y;
e.currentTarget.startDrag();
}
function onStop(e)
{
if ( e.target.dropTarget != null &&
e.target.dropTarget.parent == dest &&
e.currentTarget.name != "copy" )
{
var objectClass:Class =
getDefinitionByName(getQualifiedClassName(e.currentTarget)) as Class;
var copy:MovieClip = new objectClass();
copy.name = "copy";
this.addChild(copy);
copy.x = e.currentTarget.x;
copy.y = e.currentTarget.y;
e.currentTarget.x = sx;
e.currentTarget.y = sy;
copy.addEventListener(MouseEvent.MOUSE_DOWN, onStart);
copy.addEventListener(MouseEvent.MOUSE_UP, onStop);
}
e.currentTarget.stopDrag();
}
resetButton.addEventListener(MouseEvent.CLICK, reset);
resetButton.buttonMode = true;
function reset(event:MouseEvent):void
{
//Not sure what AS3 to add here to reset to original state
}
I have already gave you the solution here Flash AS3 Clone, Drag and Drop
Here, I am providing a detail solution on how to drag objects inside a bin and remove them.
For dropping copied objects inside a bin, after dragging is stopped, check collision with bin object. for more info see,
copiedObject.hitTestObject(binObject)
For e.g.
First create trash-can MovieClip on the stage and give it an instance name 'trashCan' and add following lines to your onStop()(below e.currentTarget.stopDrag();)function like so:
UPDATE:
var copiedObjsArr:Array = [];
function onStop(e)
{
if ( e.target.dropTarget != null &&
e.target.dropTarget.parent == dest &&
e.currentTarget.name != "copy" )
{
//Code here remains same
//.......
//Keep collecting copied letters for further access in `reset()` function
copiedObjsArr.push(copy);
}
else if(e.currentTarget.name == "copy") //this is 'else if' (newly added)
{
var tarObject:MovieClip = e.currentTarget;
// These detects collision of dragged object with the trashCan
if(tarObject.hitTestObject(trashCan)) {
//These removes dragged object from the display list (not from the memory)
removeChild(tarObject);
tarObject = null; //to garbage
}
}
e.currentTarget.stopDrag();
}
And your reset() becomes like so:
function reset(event:MouseEvent):void
{
if(copiedObjsArr.length > 0)
{
//Traverse through all copied letters
for(var i:int = 0; i<copiedObjsArr.length; i++)
{
var objToRemove:MovieClip = copiedObjsArr[i];
removeChild(objToRemove);
objToRemove = null;
}
//Finally empty the array
copiedObjsArr = [];
}
}
I have 25 objects of movie clip class named drone, and when i click it, after 2 seconds I want the object to disappear. I also have 25 timers named countdown. Here is what i do:
function clickHandler (event:MouseEvent):void{
event.currentTarget.hp--;
if(event.currentTarget.hp <= 0)
{
for(var i:int = 0;i<25;i++)
{
if(event.currentTarget == _drone[i])
{
countdown[i].start(); //start timer
}
}
}
}
Here is my timer:
for(var i:int = 0;i<25;i++)
{
countdown[i] = new Timer(2000);
countdown[i].addEventListener(TimerEvent.TIMER,timerHandler);
}
function timerHandler(e:TimerEvent):void {
//remove the drone I clicked
//I also dont know which drone i'm clicking
}
What should I do in the timerHandler to remove the object I clicked?
You can use Dictionary. Use the timer as key and movielcip as value.
import flash.utils.Dictionary;
var dict:Dictionary = new Dictionary();
function clickHandler (event:MouseEvent):void{
event.currentTarget.hp--;
if(event.currentTarget.hp <= 0)
{
for(var i:int = 0;i<25;i++)
{
if(event.currentTarget == _drone[i])
{
dict[countdown[i]] = _drone[i];//set the target mc here
countdown[i].start(); //start timer
break;
}
}
}
}
function timerHandler(e:TimerEvent):void {
var mc:MovieClip = dict[e.target] as MovieClip;//get the object been clicked
if (mc && mc.parent) {
mc.parent.removeChild(mc);//remove it
}
}
With minimal changes, set up an array to track the drones:
var arrayToRemove:Array = new Array();
and then in the click handler store drones to be removed in there:
arrayToRemove.push(event.currentTarget);
and in the timerHandler just remove the first element of the array:
removeChild(arrayToRemove.shift());
Since every delay is the same the order of the events and removals will be preserved. Although, it would probably be better to generalize the code using the above example and store all drones and timers in an arrays, so you can have any number of them.
So I'm trying to shoot multiple bullets out of my body and it all works except I have an odd problem of just one bullet showing up and updating to set position for the new ones.
I have a move able player thats supposed to shoot and I test this code by moving the player and shooting. Im taking it step by step in creating this.
The result of tracing the bulletContainer counts correctly in that its telling me that movieclips ARE being added to the stage; I Just know it comes down to some kind of logic that im forgetting.
Here's My Code (The Bullet it self is a class)
UPDATE*
Everything in this code works fine except for I stated earlier some code seems reduntned because I've resorted to a different approaches.
BulletGod Class:
public class bulletGod extends MovieClip{
//Register Variables
//~Global
var globalPath = "http://127.0.0.1/fleshvirusv3/serverside/"
//~MovieCLips
var newBullet:bulletClass = new bulletClass();
//~Boolean
var loadingBulletInProgress:Number = 0;
var shootingWeapon:Number = 0;
//~Timers
var fireBulletsInterval = setInterval(fireBullets, 1);
var bulletFireEvent;
//~Arrays
var bulletArray:Array = new Array();
var bulletType:Array = new Array();
var bulletContainer:Array = new Array();
//~Networking
var netBulletRequest:URLRequest = new URLRequest(globalPath+"bullets.php");
var netBulletVariables:URLVariables = new URLVariables();
var netBulletLoader:URLLoader = new URLLoader();
//~Bullet Image Loader
var mLoader:Loader = new Loader();
var mRequest:URLRequest = new URLRequest();
public function bulletGod() {
//Load every bullet for every gun
//Compile data to be requested
netBulletVariables.act = "loadBullets"
netBulletRequest.method = URLRequestMethod.POST
netBulletRequest.data = netBulletVariables;
netBulletLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
netBulletLoader.addEventListener(Event.COMPLETE, getBulletImages);
netBulletLoader.load(netBulletRequest);
}
private function getBulletImages(bulletImageData:Event){
//Request every bullet URL image
//Set vars
var bulletData = bulletImageData.target.data;
//Load images
for(var i:Number = 0; i < bulletData.numBullets; i++){
bulletArray.push(bulletData["id"+i.toString()]);
bulletType.push(bulletData["bullet"+i.toString()]);
//trace(bulletData["id"+i]+"-"+bulletData["bullet"+i]);
}
//All the arrays have been set start firing the image loader/replacer
var imageLoaderInterval = setInterval(imageReplacer, 10);
}
private function imageReplacer(){
//Check to see which image needs replacing
if(!loadingBulletInProgress){
//Begin loading the next image
//Search for the next "String" in the bulletType:Array, and replace it with an image
for(var i:Number = 0; i < bulletType.length; i++){
if(getQualifiedClassName(bulletType[i]) == "String"){
//Load this image
mRequest = new URLRequest(globalPath+"ammo/"+bulletType[i]);
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadImage);
mLoader.load(mRequest);
//Stop imageReplacer() while we load image
loadingBulletInProgress = 1;
//Stop this for() loop while we load image
i = 999;
}
}
}
}
private function loadImage(BlackHole:Event){
//Image has loaded; find which array slot it needs to go into
for(var i:Number = 0; i <= bulletType.length; i++){
if(getQualifiedClassName(bulletType[i]) == "String"){
//We found which array type it belongs to; now replace the text/url location with the actual image data
var tmpNewBullet:MovieClip = new MovieClip;
tmpNewBullet.addChild(mLoader);
//Add image to array
bulletType[i] = tmpNewBullet;
//Restart loadingBullets if there are more left
loadingBulletInProgress = 0;
//Stop for() loop
i = 999;
}
}
}
//###############################################################################################################################################
private function fireBullets(){
//If player is holding down mouse; Fire weapon at rate of fire.
if(shootingWeapon >= 1){
if(bulletFireEvent == null){
//Start shooting bullets
bulletFireEvent = setInterval(allowShooting, 500);
}
}
if(shootingWeapon == 0){
//The user is not shooting so stop all bullets from firing
if(bulletFireEvent != null){
//Strop firing bullets
clearInterval(bulletFireEvent);
bulletFireEvent = null
}
}
}
private function allowShooting(){
//This function actually adds the bullets on screen
//Search for correct bullet/ammo image to attach
var bulletId:Number = 0;
for(var i:Number = 0; i < bulletArray.length; i++){
if(bulletArray[i] == shootingWeapon){
//Bullet found
bulletId = i;
//End For() loop
i = 999;
}
}
//Create new bullet
//Create Tmp Bullet
var tmpBulletId:MovieClip = new MovieClip
tmpBulletId.addChild(newBullet);
tmpBulletId.addChild(bulletType[bulletId]);
//Add To Stage
addChild(tmpBulletId)
bulletContainer.push(tmpBulletId); //Add to array of bullets
//Orientate this bullet from players body
var bulletTmpId:Number = bulletContainer.length
bulletTmpId--;
bulletContainer[bulletTmpId].x = Object(root).localSurvivor.x
bulletContainer[bulletTmpId].y = Object(root).localSurvivor.y
//addChild(bulletContainer[bulletTmpId]);
}
//_______________EXTERNAL EVENTS_______________________
public function fireBullet(weaponId:Number){
shootingWeapon = weaponId;
}
public function stopFireBullets(){
shootingWeapon = 0;
}
}
}
BulletClass:
package com{
import flash.display.*
import flash.utils.*
import flash.net.*
import flash.events.*
public class bulletClass extends MovieClip {
public var damage:Number = 0;
public function bulletClass() {
//SOME MOVEMENT CODE HERE
}
public function addAvatar(Obj:MovieClip){
this.addChild(Obj);
}
}
}
Well ... if I may say so, this code looks quite wrong. Either something is missing from the code or this code will never make the bullets fly.
First off, you can set x and y of the new bullet directly (replace everything after "orientate this bullet from players body" with this):
tmpBulletId.x = Object(root).localSurvivor.x;
tmpBulletId.y = Object(root).localSurvivor.y;
Perhaps this already helps, but your code there should already do the same.
But to let these bullets fly into any direction, you also need to add an event listener, like so:
tmpBulletId.addEventListener(Event.ENTER_FRAME, moveBullet);
function moveBullet(e:Event) {
var movedBullet:MovieClip = MovieClip(e.currentTarget);
if (movedBullet.x < 0 || movedBullet.x > movedBullet.stage.width ||
movedBullet.y < 0 || movedBullet.y > movedBullet.stage.height) {
// remove move listener, because the bullet moved out of stage
movedBullet.removeEventListener(Event.ENTER_FRAME);
}
// remove the comment (the //) from the line that you need
MovieClip(e.currentTarget).x += 1; // move right
// MovieClip(e.currentTarget).y -= 1; // move up
// MovieClip(e.currentTarget).x -= 1; // move left
// MovieClip(e.currentTarget).y += 1; // move down
}
This example lets your bullet fly to the right. If you need it flying into another direction, just comment out the line with the "move right" comment and uncomment one of the other lines.
This is of course a very simple example, but it should get you started.
I hope this helps, and that my answer is not the wrong answer to the question.
As far as I have expirienced it you can have only one copy of MovieClip object added to specific child. Best approach is to use ByteArray for the clip source and instantiate new MovieClip and pass the ByteArray as a source. It have something to do with child/parent relation since a DisplayObject can have only one parent (and a way to detach the object from scene too).
Well i ended up writeing the whole code from scratch for a 3rd time and ran into a similar problem and just for reference to anybody else that comes to a problem thats random as this one i found that problem was likly does to a conversion error somewhere that doesn't necessarily break any compiling rules. Just that i was calling a movieclip and not the class it self.