Movieclips whack-a-mole different cords on moles - actionscript-3

I have created a flash whack-a-mole game, and coded the 9 different x and y cordinates the 4 moles can come up on. But I can't code it so that the moles can never have the same x and y cordinates.
I have tried this code: (Barney and mulvarp is two moles. .flytt(); is the command that gives the mole a new place to be.
if( Barney.x == mulvarp.x ){
Barney.flytt();
}
Barney.addEventListener(MouseEvent.CLICK, flyttb);
function flyttb(evt:MouseEvent){
barneyAu.play();
//returnFourPositionsF();
Barney.flytt();
teller-=4;
score.text=teller+"p";
barneyTimer.reset();
barneyTimer.start();
}
mulvarp.addEventListener(MouseEvent.CLICK, flyttm);
function flyttm(evt:MouseEvent){
squishRiktig.play();
mulvarp.flytt();
teller+=1;
score.text=teller+"p";
mulvarpTimer.reset();
mulvarpTimer.start();
}
Kone.addEventListener(MouseEvent.CLICK, flyttmk);
function flyttmk(evt:MouseEvent){
squishRiktig.play();
Kone.flytt();
teller+=2;
score.text=teller+"p";
koneTimer.reset();
koneTimer.start();
}
Baby.addEventListener(MouseEvent.CLICK, flyttmb);
function flyttmb(evt:MouseEvent){
squishRiktig.play();
Baby.flytt();
teller+=3;
score.text=teller+"p";
babyTimer.reset();
babyTimer.start();
}
And this is the .flytt(); function I got inside all of the moles in a actionscript:
function flytt():void{
var flyttUt:int=Math.random() * 8;
if(flyttUt==0){
x=243,30;
y=171,65
}
if(flyttUt==1){
x=630,55;
y=170,25;
}
if(flyttUt==2){
x=999,85;
y=175,55;
}
if(flyttUt==3){
x=244,85;
y=363,85;
}
if(flyttUt==4){
x=632,75;
y=360,20;
}
if(flyttUt==5){
x=996,25;
y=359,50;
}
if(flyttUt==6){
x=228,45;
y=572,40;
}
if(flyttUt==7){
x=627,75;
y=570,95;
}
if(flyttUt==8){
x=650,60;
y=382,05;
}
}
I got an advice on maybe using this and call returnFourPositionsF(); but I am unsure on how to put all the moles into one, since they all have different timers, and I don't want them to change position even tho only one is changing.
var positionA:Array = [ [243.30,171.65],[630.55,170.25],[999.85,175.55],[244.85,363.85],[632.75,360.20],[996.25,359.50],[228.45,572.40],[627.75,57.95],[650.60,382.05] ];
function returnFourPositionsF():Array{
shuffle(positionA);
return [positionA[0],positionA[1],positionA[2],positionA[3]]
}
function shuffle(a:Array) {
var p:int;
var t:*;
var ivar:int;
for (ivar = a.length-1; ivar>=0; ivar--) {
p=Math.floor((ivar+1)*Math.random());
t = a[ivar];
a[ivar] = a[p];
a[p] = t;
}
}

Run your shuffled array through a Dictionary like so.
import flash.utils.Dictionary;
var ar:Array = [[200, 100], [600, 400], [200, 100], [479, 239]];
var dict:Dictionary = new Dictionary();
for(var i:int=0;i<ar.length;i++)
{
dict[ar[i]] = ar[i];
}
var temp:Array = [];
for(var item in dict)
{
temp.push(item);
}
Dictionaries can't have duplicate keys, so each duplicate key is removed. From there, you should be able to use this logic to avoid duplicate positions.

Related

Actionscript error 1176: Comparison between a value with static type Number and a possibly unrelated type String?

For lines 18 and 24 Actionscript seems to be unhappy with my if statements. Being really new to this I don't know how to rectify the issue if any.
var strName:String;
var strSystem:String;
var strHeight:String;
var numHeight:Number;
var numSystem:Number;
var strOut:String;
var strOut2:String;
enter_btn.addEventListener(MouseEvent.CLICK, onClick);
function onClick(event:MouseEvent):void {
strName=txt_Name.text;
strSystem=txt_System.text;
numSystem=Number(strSystem)
strHeight=txt_Height.text;
numHeight=Number(strHeight);
if (numSystem == "M"){
var numWeight:Number= numHeight*numHeight*25;
var strWeight:String=String(numWeight);
strOut=strName+ "'s ideal weight is" +strWeight+"kilograms.";
txt_Answer.text=strOut
}
if (numSystem == "I"){
var numWeight2:Number= (numHeight*numHeight*25)/703
var strWeight2:String=String(numWeight);
strOut2= strName+"'s ideal weight is" +strWeight2 + "pounds";
}
{
}
}
What is with
}
{
}
}
at the end of your class? It's wrong as the middle {} does not start with any condition statement.
var strWeight:String=String(numWeight); should be var strWeight:String= numWeight.toString(); or var strWeight:String= numWeight.toFix();

Collecting and identifying functions within an array in actionscript

So, I want to do something where I collect functions to be invoked later when a certain condition is met. E.g.
function doSomething(someArg:Object):void {
if (conditionIsFalse){
operationsToDoWhenConditionIsTrue.push(function(){
doSomething(someArg);
});
}
}
function onConditionBecomingTrue():void {
while (operationsToDoWhenConditionIsTrue.length > 0){
operationsToDoWhenConditionIsTrue.shift()();
}
}
So far so good. However at some point I want to iterate over the operationsToDoWhenConditionIsTrue and identify and replace a function. In pseudo code inside the doSomething method it would be:
function doSomething(someArg:Object):void {
if (conditionIsFalse){
for (var i:int = 0; i<operationsToDoWhenConditionIsTrue; i++){
// pseudo code here
if (typeof operationsToDoWhenConditionIsTrue[i] == doSomething){
operationsToDoWhenConditionIsTrue[i] = doSomething(someArg);
}
}
}
}
Basically if doSomething is called twice, I only want operationsToDoWhenConditionIsTrue to hold the most recent invocation. Obviously since the invocations are wrapped in function(){} all the functions are the same. Is there any way I can accomplish what I want?
Create an identifier function that can identify the operations you want to detect as the same. Assign the ID as a property of the anonymous function that you add to the queue. When you iterate over the queue, record IDs in a collection. Don't execute the operation if it's already in the collection.
function doSomething(someArg:Object):void {
if (conditionIsFalse){
var operation = function(){
doSomething(someArg);
};
operation.operationID = objID(...);
operationsToDoWhenConditionIsTrue.push(operation);
}
}
function onConditionBecomingTrue():void {
var done = {}, f;
while (operationsToDoWhenConditionIsTrue.length > 0){
f = operationsToDoWhenConditionIsTrue.shift();
if (! f.operationID in done) {
done[f.operationID] = true;
f()
}
}
}
As a more efficient variant of this, you can index the queue by IDs, so that a function can be added only once to the queue. However, you will lose control over the order that operations are executed.
var operationsToDoWhenConditionIsTrue:Object = {};
function doSomething(someArg:Object):void {
if (conditionIsFalse){
operation.operationID = ...;
operationsToDoWhenConditionIsTrue[objID(...)] = function(){
doSomething(someArg);
};
}
}
function onConditionBecomingTrue():void {
for (id in operationsToDoWhenConditionIsTrue){
operationsToDoWhenConditionIsTrue[id]();
}
operationsToDoWhenConditionIsTrue = {};
}
If you need to preserve the sequence (so that operations are executed in order they were first added to the queue, or in the order they were last added), create a queue type that can be indexed by both ID and sequence, which you can do by storing mappings between the index types. Note: the following is untested.
class OperationQueue {
protected var queue:Array = [];
protected var idToSeq:Object = {};
public function push(op:Function):void {
/* Orders by last insertion. To order by first insertion,
simply return if the operation is already in the queue.
*/
if (op.id in this.idToSeq) {
var seq = this.idToSeq[op.id];
delete this.queue[seq];
}
this.queue.push(op);
this.idToSeq[op.id] = this.queue.length-1;
}
public function runAll():void {
var op;
while (this.queue.length > 0) {
if ((op = this.queue.shift())) {
delete this.idToSeq[op.id];
op();
}
}
}
}

how to compare two array collection using action script

how to compare two arraycollection
collectionArray1 = ({first: 'Dave', last: 'Matthews'},...........n values
collectionArray = ({first: 'Dave', last: 'Matthews'},...........n values
how to compare..if equal just alert nochange if not alert chaged
If you just want to know if they are different from each other, meaning by length, order or individual items, you can do the following, which first checks to see if the lengths are different, then checks to see if the individual elements are different. This isn't terribly reusable, it's left as an exercise for the reader to split this apart into cleaner chunks :)
public function foo(coll1:ArrayCollection, coll2:ArrayCollection):void {
if (coll1.length == coll2.length) {
for (var i:int = 0; i < coll1.length; i++) {
if (coll1[i].first != coll2[i].first || coll1[i].last != coll2[i].last) {
Alert.show("Different");
return;
}
}
}
Alert.show("Same");
}
/* elements need to implement valueOf
public function valueOf():Object{}
*/
public static function equalsByValueOf(
first:ArrayCollection,
seconde:ArrayCollection):Boolean{
if((first==null) != (seconde==null) ){
return false;
}else if(!first && !seconde){
return false;
}
if(first.length!=seconde.length){
return false;
}
var commonLength:int = first.length;
var dictionary:Dictionary = new Dictionary();
for(var i:int=0;i<commonLength;i++){
var item1:Object = first.getItemAt(i);
var item2:Object = seconde.getItemAt(i);
dictionary[item1.valueOf()]=i;
dictionary[item2.valueOf()]=i;
}
var count:int = 0;
for (var key:Object in dictionary)
{
count++;
}
return count==commonLength;
}
/* valueOf sample
* something like javaObject.hashCode()
* use non changing fields(recommended)
*/
public function valueOf():Object{
return "_"+nonChangeField1+"_"+nonChangeField2+"...";
}
I was going to say this.
if(collectionArray === collectionArray1)
But that wont work (not triple = signs). As === is used to see classes.
I would write a function called check if object exists in array.
Create an array to hold elements that are not found. eg notFound
in Collection1 go through all the element and see if they exist in Collection2, if an element does not exist, add it to the notFound array. Use the function your created in step1
Now check Collection2, if an element is not found add it to the notFound array.
There is no 5.
Dude, use the mx.utils.ObjectUtil... the creators of actionscript have already thought about this.
ObjectUtil.compare(collection1, collection2) == 0;

AS3: indexOf() sub-array in a multi-dimensional array

var asdf:Array = [ [1,1] ];
trace( asdf.indexOf( [1,1] ) ); // -1
Why can't indexOf() find the [1,1] array?
Here is a little function I wrote a while ago that works great. I included a lot of comments and an example search/function to output the results.
// set up a multidimensional array that contains some data
var myArray:Array = new Array();
myArray.push(["granola","people... are great"," 4 ","10"]);
myArray.push(["bill","orangutan","buster","keaton"]);
myArray.push(["steve","gates","24","yes, sometimes"]);
myArray.push(["help","dave","jobs","hal"]);
// here we set up some properties on the array object to hold our search string and our results
myArray.myTarget = "steve";
myArray.myResults = [];
// now we call the search
myArray.forEach(multiSearch);
// this is the function that does all the heavy lifting....
function multiSearch(element:*, index:int, array:Array)
{
// see if we have a match in this array and pass back its index
for(var i:* in element)
{
if( element[i].indexOf( array.myTarget ) > -1 )
{
var tempArray:Array = array.myResults;
tempArray.push([index,i]);
array.myResults = tempArray;
}
}
}
// -------------------------------------------------------------------------------
// all the code below is OPTIONAL... it is just to show our results
// in the output window in Flash so you know it worked....
var printArray:Array = myArray.myResults;
for(var i:* in printArray)
{
trace("TARGET FOUND #: "+printArray[i][0]+", "+printArray[i][1]+" = "+myArray[ printArray[i][0] ][ printArray[i][1] ]);
}
// -------------------------------------------------------------------------------
It fails because when you do a [x,y] you are creating a new array, adsf contains one array and indexOf search for another one.
try:
trace([1,1] == [1,1]);
You will see that it prints false, since array are compare by reference.
One quick indexOf function, arrange it to suit your needs:
function isElmEquals(e1:*, e2:*):Boolean {
return (e1==e2);
}
function isArrayEquals(a1:Array, a2:Array):Boolean {
if (a1==a2)
return true;
if ((a1==null) || (a2==null)) {
return false;
}
if (a1.length!=a2.length)
return false;
for (var i:int=0;i<a1.length;i++){
if (!isElmEquals(a1[i], a2[i]))
return false;
}
return true;
}
function indexOf(value:Array, into:Array):int{
var i:int = -1;
into.some(
function(item:*, index:int, array:Array):Boolean {
if (isArrayEquals(item as Array, value)) {
i = index;
return true;
}
return false;
}
);
return i;
}
var i:int=indexOf([1,1], [[-1,1], [0,1], [1,1], [1,-1]]);
trace(i);
var j:int=indexOf([1,2], [[-1,1], [0,1], [1,1], [1,-1]]);
trace(j);
this works. probably because the inner array is typed.
var qwer:Array = [1,1];
var asdf:Array = [qwer];
trace( asdf.indexOf( qwer ) ); // 0

A* algorithm works OK, but not perfectly. What's wrong?

This is my grid of nodes:
I'm moving an object around on it using the A* pathfinding algorithm. It generally works OK, but it sometimes acts wrongly:
When moving from 3 to 1, it correctly goes via 2. When going from 1 to 3 however, it goes via 4.
When moving between 3 and 5, it goes via 4 in either direction instead of the shorter way via 6
What can be wrong? Here's my code (AS3):
public static function getPath(from:Point, to:Point, grid:NodeGrid):PointLine {
// get target node
var target:NodeGridNode = grid.getClosestNodeObj(to.x, to.y);
var backtrace:Map = new Map();
var openList:LinkedSet = new LinkedSet();
var closedList:LinkedSet = new LinkedSet();
// begin with first node
openList.add(grid.getClosestNodeObj(from.x, from.y));
// start A*
var curNode:NodeGridNode;
while (openList.size != 0) {
// pick a new current node
if (openList.size == 1) {
curNode = NodeGridNode(openList.first);
}
else {
// find cheapest node in open list
var minScore:Number = Number.MAX_VALUE;
var minNext:NodeGridNode;
openList.iterate(function(next:NodeGridNode, i:int):int {
var score:Number = curNode.distanceTo(next) + next.distanceTo(target);
if (score < minScore) {
minScore = score;
minNext = next;
return LinkedSet.BREAK;
}
return 0;
});
curNode = minNext;
}
// have not reached
if (curNode == target) break;
else {
// move to closed
openList.remove(curNode);
closedList.add(curNode);
// put connected nodes on open list
for each (var adjNode:NodeGridNode in curNode.connects) {
if (!openList.contains(adjNode) && !closedList.contains(adjNode)) {
openList.add(adjNode);
backtrace.put(adjNode, curNode);
}
}
}
}
// make path
var pathPoints:Vector.<Point> = new Vector.<Point>();
pathPoints.push(to);
while(curNode != null) {
pathPoints.unshift(curNode.location);
curNode = backtrace.read(curNode);
}
pathPoints.unshift(from);
return new PointLine(pathPoints);
}
NodeGridNode::distanceTo()
public function distanceTo(o:NodeGridNode):Number {
var dx:Number = location.x - o.location.x;
var dy:Number = location.y - o.location.y;
return Math.sqrt(dx*dx + dy*dy);
}
The problem I see here is the line
if (!openList.contains(adjNode) && !closedList.contains(adjNode))
It may be the case that an adjNode may be easier(shorter) to reach through the current node although it was reached from another node previously which means it is in the openList.
Found the bug:
openList.iterate(function(next:NodeGridNode, i:int):int {
var score:Number = curNode.distanceTo(next) + next.distanceTo(target);
if (score < minScore) {
minScore = score;
minNext = next;
return LinkedSet.BREAK;
}
return 0;
});
The return LinkedSet.BREAK (which acts like a break statement in a regular loop) should not be there. It causes the first node in the open list to be selected always, instead of the cheapest one.