Designing some lessons in AS3 for the HS multimedia class I teach.
I haven't tried to teach this in my class in a few years, so I'm a bit rusty. It's also possible my script is not as smooth as it could be as I've based it on some AS2 work I did quite sometime ago.
That said, this little bit of code runs for about thirty seconds and then stops. No error, no feedback outside the trace command I put in to track array length.
This is part of a lesson series for getting the kids in the direction of writing some games in AS3. In this one we're looking at creating random timing and random placement. We've already covered motion, properties, variables, listeners, and functions.
Here's the code:
import flash.events.Event;
var firstMeteor:Number = 1;
var timeSinceLast:Number = 0;
var lastMeteor:Number = 0;
var totalMeteors = 60;
var metProp=.08;
var rocksBox:Array = new Array;
var dropSpeed:Number = 15;
var lowLimit:Number = 350;
stage.addEventListener(Event.ENTER_FRAME,dropRocks);
stage.addEventListener(Event.ENTER_FRAME,moveRocks);
function dropRocks(e:Event):void{
if(lastMeteor<totalMeteors) {
if(Math.random() < metProp) {
lastMeteor++;
var rock:meteor = new meteor;
addChild(rock);
rocksBox.push(rock);
rock.x = Math.random()*500;
rock.y = 20;
timeSinceLast = 0;
}
}
timeSinceLast++;
}
function moveRocks(e:Event):void {
for(var i:int = rocksBox.length-1; i>=0; i--) {
rocksBox[i].y += dropSpeed;
if(rocksBox[i].y>lowLimit) {
removeChild(rocksBox[i]);
rocksBox.splice(i,1);
trace(rocksBox.length);
}
}
}
In your code, you drop a rock only when the total count of the meteors created so far (i.e: the lastMeteor), has not yet reached the maximum amount of totalMeteors you specified! When it reached the maximum, then if(lastMeteor<totalMeteors) won't let any other "meteor" creation happen!!
Related
It shows an error when written this script has a package that cannot be nested how can I resolve the problem.
If not can anyone give me a new code so that I can try to make the new file?
I have this file in previous stack AS3 Bingo ticket generator
but i couldnt understan how to use it.
package {
import flash.display.Sprite;
import flash.text.TextField;
public class Main extends Sprite{
public var boards:Array = new Array();
private static const AMAUNT_BOARDS:uint = 6;
private static const NUMBER_FIELD_SIZE:uint = 20;
public function Main() {
for(var i:uint = 0; i < AMAUNT_BOARDS; i++)
{
var numbers:Array = genNumbers();
numbers = deleteFields(numbers);
var board:Sprite = getBoard(numbers);
board.y = NUMBER_FIELD_SIZE * 4 * i;
boards.push(board);
addChild(board);
}
}
//generates a 2 Dimensional Array (3x9) with TextFields
//populates the according Numbers and returns a board Sprite
private function getBoard(n:Array):Sprite
{
var s:Sprite = new Sprite();
var a:Array = new Array();
for(var i:uint = 0; i < 3; i++)
{
var b:Array = new Array();
for(var k:uint = 0; k < 9; k++)
{
//create TextFields
var tf:TextField = new TextField();
tf.x = k * NUMBER_FIELD_SIZE;
tf.y = i * NUMBER_FIELD_SIZE;
tf.border = true;
tf.width = NUMBER_FIELD_SIZE;
tf.height = NUMBER_FIELD_SIZE;
if(n[k][i] != 0) // adds the number if the value isn't 0
tf.text = n[k][i]; // Note that i am switching k & i because the number Array is 9x3
b.push(tf);
s.addChild(tf);
}
}
return s;
}
// Turns 4 random numbers out of the lines into 0 And returns the Array
private function deleteFields(a:Array):Array
{
for(var i:uint = 0; i < 3; i++)
{
var r:RandomPlus = new RandomPlus(8,0);
for(var k:uint = 0; k < 4; k++)
{
var t:uint = r.getNum();
a[t][i] = 0;
}
}
return a;
}
// Generates and returns a 2 Dimensional Array (9x3) with random numbers
private function genNumbers():Array
{
var a:Array = new Array();
var st:uint = 1;
var en:uint = 9;
for(var i:uint = 0; i < 9; i++)
{
var line:Array = new Array();
var ran:RandomPlus = new RandomPlus(en,st);
if(i == 0)//accounting for the number differnenz at start
st--;
if(i==7)//accounting for the number differnenz at end
en ++;
st += 10;
en += 10;
for(var e:uint = 0; e < 3; e++)
line[e] = ran.getNum();
a.push(line);
}
return a;
}
}
}
TL;DR: "Main" in the class definition may have to be changed conflict of already existing name. Extends sprite may need to be changed to extends movieclip. RandomPlus either needs an import you don't have or needs to be made into a symbol and exported to Actionscript.
Ok, so a few things:
If you are really putting the code into the stage code area, then you can't use the private identifier.
Unless RandomPlus is an object that you have defined in the stage it is probably either not a method you can use or you don't have the right imports for it. Look up what imports you need for RandomPlus or if it is an object defined in the stage then you may need to turn it into a symbol or if you have already export it to flash ActionScript I think. To do this you have to check the checkbox in the middle of the symbol creation page. It will always give you the error when you do this, but don't worry it is fine that way.
Third thing is that I never extend sprite in the class definition, I always do extends movieclip(not sure of the capitalization, but you can look that up). You may also be running into an error from using "Main" as the name because it may be a conflict with a name or method already defined in flash in general.
One last thing is for the variable declaration(mostly just for making the code more readable). While it is good to not declare variables as global when you don't have to, I tend to like having most of the variables up at the top, because I like to be able to see most of the declarations in one space. It's not necessary, really just a personal opinion, and I know a lot of experienced coders will say to do what you did, but if you want to use the arrays in multiple functions then sometimes it is easier to just declare them globally rather than having to pass a million things in the function call and then having to figure out later where all the variable declarations are called and where they are being passed as arguments. Again it's more of a coder's choice, but you can also just do whatever you feel more comfortable with rather than just following the already laid out rules by people who have more experience coding.
Another optional fix to the organization might be to name variables something meaningful so as to not forget what they are all doing. I am bad at naming as well, but I think it's really better to name them something better than just a single letter or two.
Another thing that can help is placing trace(code or "text"); in different places to see what's going wrong once you have the compiler happy.
im creating a simple game which the objective is to deliver items the fastest as you can.There are no other score points except time, i manage to make the time start as the game begin and stop when the objective is done, but how do i save the time when it stop and make it appear at the home page as the "Best Time"? for now im still using other score points with the time, but im going to delete it and use only Time instead, help me, thanks in advance :)
these are several codes where i manage to stop the time, just write it here in case if it is needed, will write other codes as well if needed.
if (score==15) {
time1.stop();
gotoAndPlay('resultframe')
stop();
time1.stop();
score2_txt.text = String(score);
timeField2.text = String(""+minute+":"+second+"");
response_txt.text = "Well Done! You won!";
var minute = 5;
var second = 59;
var time1:Timer = new Timer (1000);
time1.addEventListener(TimerEvent.TIMER, calcTime);
function calcTime(e:TimerEvent):void {
second -= 1;
if(second == 00){
minute -= 1;
second = 59;
}
timeField.text = String(""+minute+":"+second+"");
}
import flash.utils.getTimer;
var startTime:int;
function chronometerStart():void
{
startTime = getTimer();
}
function chronometerStop():int
{
var now:int = getTimer();
var time:int = now - startTime;
return time;
}
the getTimer()-method returns the number of milliseconds that have elapsed since the swf gegan to run.
Greetings André
I'm working on an inventory system I made following a short tutorial that leaves you stranded. I've managed to get the items removed and rearrange to the correct order somewhat. For some reason though, if I click on the last item in my inventory, then on the first item, the items do not rearrange correctly.
public class Inventory {
var itemsInInventory:Array;
var inventorySprite:Sprite;
var itemNum:int;
public function Inventory(parentMC:MovieClip) {
itemNum=0;
itemsInInventory = new Array();
inventorySprite = new Sprite();
inventorySprite.x = 50;
inventorySprite.y = 360;
parentMC.addChild(inventorySprite);
}
public function makeInventoryItems(arrayOfItems:Array){
for(var i:int = 0; i < arrayOfItems.length; i++){
arrayOfItems[i].addEventListener(MouseEvent.CLICK, getItem);
arrayOfItems[i].buttonMode = true;
}
}
public function getItem(e:MouseEvent){
var item:MovieClip = MovieClip(e.currentTarget);
itemsInInventory.push(item);
inventorySprite.addChild(item);
item.x = (itemsInInventory.length-1)*40;
item.y = 0;
item.removeEventListener(MouseEvent.CLICK, getItem);
item.addEventListener(MouseEvent.CLICK, useItem);
}
public function useItem(e:MouseEvent){
var item:MovieClip = MovieClip(e.currentTarget);
itemNum = item.x;
inventorySprite.removeChild(item);
itemsInInventory.splice(item, 1);
sortInventory();
}
public function sortInventory(){
for(var i:int = 0; i < itemsInInventory.length; i++){
if(itemsInInventory[i].x > itemNum){
itemsInInventory[i].x -= 40;
}
}
itemNum=0;
}
}
I belive thats all the coding info I need to provide for help solving this mystery.
Also, a link to the game for testing. If you would like a link for a download of the game, please ask.
LINK
Instead of substracting 40px, just set their position again:
for(var i:int = 0; i < itemsInInventory.length; i++){
itemsInInventory[i].x = i*40;
}
Also, I did not even know that it is possible to give an object reference to the splice function, I would rather use:
itemsInInventory.splice(itemsInInventory.indexOf(item), 1);
And remove the event listener from the item when you delete it from the inventory in the useItem function.
item.removeEventListener(MouseEvent.CLICK, useItem);
EDIT:
With Flash Player 10, Adobe introduced the Vector class which is kind of the same as the Array class, but it can only store one data type. In your case it would be MovieClip or Sprite. The Vector class is singificantly faster and more developer friendly because you can see the help from the IDE when you are typing myVector[i].. I recommend using that instead, although there is nothing wrong with Array. It is just outdated a bit, but is helpful when you want to store more data types.
myVector:Vector.<MovieClip> = new Vector.<MovieClip>();
I'm sure this question has been asked a million times in a million ways, but I would appreciate the help anyway. I am working on a Flash Mastermind clone and have a movie clip with 12 colored "pegs" and a "hole" image. How would I code a statement that will pick five random frames and not just the first five frames? I have the barest idea, but I'm not entirely sure if it's right:
var totalColors:Number = 12;
var maxColors:Number = 5;
var chosenColors:Array:
for(var i:Number = 1; i<totalColors; i++)
{
chosenColors[i] = Math.floor(Math.random()*totalColors)+1
}
Thanks a lot in advance for your help!
Please note that the movieclip has been rearranged since I wrote this; I moved the first frame - the "hole" to another layer.
EDIT: Pan has helped a lot since I first asked this question. To test it I decided to expand on my Bejeweled clone code. I added five more shapes to the original 7. At first I thought the line "newPiece.type = Math.ceil(Math.random() * chosenColors.length);" inside the loop, so I commented the quoted line, which was outside of the j loop and part of the original code, and replaced it with this:
newPiece.type = chosenColors[j];
I am very sorry if this seems elementary to some; I am not the strongest programmer, especially when making games. I am far better at ASP.NET and UI design, but game development has always appealed to me for some weird, possibly insane reason. Anyway, here is part of the method for creating a new jewel. The two for loops are pan's code for choosing seven random frames out of twelve. Unfortunately, the movie still picks the first seven frames from the movie clip.
//i goes through all of the possible colors and adds them to the temp array
for (var i:uint = 1; i <= newPiece.totalFrames; i++)
{
temp.push(i);
}
//j chooses seven colors out of the array of all possibilities
for (var j:int = 0; j < numPieces; j++)
{
//index is the frame that has been chosen randomly
var index:int = int(Math.random() * temp.length);
chosenColors.push(j);
chosenColors[j] = temp[index];
//remove the index
temp.splice(index, 0);
}
newPiece.type = Math.ceil(Math.random() * chosenColors.length);
Again, if I've confused anyone with my bad code to English translation, here is an image of my running game and its Jewel movieclip so you will hopefully see what I mean.
var totalColors:Number = 12;
var maxColors:Number = 5;
var chosenColors:Array = [];
var temp:Array = [];
for(var i:Number = 1; i <= totalColors; i++)
{
temp.push(i);
}
for (var j:int = 0; j < maxColors; j++)
{
var index:int = int(Math.random()*temp.length);
chosenColors[j] = temp[index];
//remove the index
temp.splice(index, 1);
}
I've been working on a Flash drag-and-drop scene using AS3. The scene is broken into 4 "zones", and each zone has 5 targets. I've used arrays to allow the mc's to be dropped in their respective zones, without any particular order. All of this works as it should.
The issue I have it that there are 2 "puzzle" pieces (MCs) that are identical to one-another in terms of how they visually display on the screen. I've set up the arrays to allow for both to be dropped in zone 1 or zone 2. However, I'd like to set it up so that if "identical piece 1" gets dropped into zone 1, then "identical piece 2" cannot also be dropped into that same zone.
Any suggestions for how to go about doing this?
How about setting a flag in every zone that tells if a piece has already been attached to it?
If your zones are MovieClips you can simply add variables to them, and set mcTarget.isTaken = true when a piece gets attached to it. If they are simply coordinates, you can use a global array like this
private mZoneTaken:Array = new Array();
for (var i:int=0; i<4; i++)
{
mZoneTaken[i] = new Array();
for (var j:int = 0; j<5; j++)
{
mZoneTaken[i][j] = false;
}
}
Then whenever a piece is dropped on a zone, you can set its flag to true, allowing you to prevent any further piece from getting attached to it.
Personally, I would have an array/Vector (Vectors are much, much faster. Though they can be a royal pain to use) of objects within each individual zone. You keep this updated at all times. If you remove one, you use splice(indexOf(obj),1) to remove it from the array.
For your problem, I would do this:
var p1:Sprite = new Sprite();
var p2:Sprite = new Sprite();
var zoneArray:Array = new Array();//there would be one for each zone, simplified it here
//this code would run whenever an object enters the zone
function zoneEnter(e:Event = null):void{
var currentZone:Sprite; //set this equal to the zone the sprite just entered
var currentObject:Sprite = e.currentTarget as Sprite; //this way we know which object just entered currentZone
if ( currentObject == p1 && zoneArray.indexOf(p2) >= 0 ) {
//prevent it from entering the zone
}
if ( currentObject == p2 && zoneArray.indexOf(p1) >= 0 ) {
//prevent it from entering the zone
}
}
There are obviously some limitations here if you are looking at a lot of objects. But if you know, for sure, there will only be two, I think this would be the way to go. If there will be more, you would need to create some kind of control structure that would allow you to check an object against other objects. I could elaborate and give a sample of what I am talking of here if it's needed. It's a tad bit complex, but not hard to implement.
EDIT 10-17-12: Added in example code of how the more advanced logic would look.
var puzzleMap:Array = new Array();
var piece1:Piece = new Piece(); //this is the puzzle piece we'll be checking
var piece2:Piece = new Piece();
var piece3:Piece = new Piece();
var piece1Objs:Array = [piece2,piece3];
var piece2Objs:Array = [piece1,piece3];
puzzleMap.push({piece:piece1,others:piece1Objs});
puzzleMap.push({piece:piece2,others:puzzle2Objs);
private function stopDragHandler(e:MouseEvent = null):void{
var space:Space = space; //this is the space the object was dropped into (I don't know how you identify them, so this is pseudo code)
var valid:Boolean = true; //we'll check for a bad drop since it's easiest
if (event.target.dropTarget != null && MovieClip(event.target.dropTarget.parent).allowed.indexOf(event.target) > -1){
for ( var i:Number = 0; i < puzzleMap.length; i++ ) {
var current:Object = puzzleMap[i];
if ( current == e.currentTarget ) {
for ( var j:Number = 0; j < current.others.length; j++ ) {
var checkAgainst:Piece = current.others[i] as Piece;
if ( space.currentObjects.indexOf(checkAgainst) < 0 ) {
valid = false;
break;
}
}
}
}
if ( !valid ) {
//prevent the drop here
}
}
}