Trying to create collisions - actionscript-3

var i:int = 0;
stage.focus=stage;
var Walls:Array = [Wall,Wall1];
addEventListener(Event.ENTER_FRAME,HitDetection);
function HitDetection(event:Event):void{
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
function myKeyDown(e:KeyboardEvent):void
{
{
if (e.keyCode == Keyboard.LEFT)
{
if (KeemStar1.hitTestObject(Walls[i])) {
trace("1")
KeemStar1.x -=-0.1;
}
else
{
KeemStar1.x -=0.1;
}
}
if (e.keyCode == Keyboard.RIGHT)
{
{
if (KeemStar1.hitTestObject(Walls[i])) {
KeemStar1.x -=-0.1;
trace ("n")
}
else
{
KeemStar1.x +=0.1;
}
}
}
}
}
}
It only collides with the first Wall, instead of every wall in the array. I've tried everything but I can't figure it out I'm kind of new to actionscrip3 so I'm not sure what to do. Thanks !!

You aren't looping through the array as you need to. It should look more like this:
for (var i: int = 0; i < Walls.length; i++){
// code for collision detection against Walls[i]
}
that code will loop through as many items as you have in that array, checking collision against each one.
Also your if statements are bracketed totally wrong. Should be:
if (condition){
// code
}
replace condition with whatever you want (like KeemStar1.hitTestObject(Walls[i])) and replace //code with what should happen if the condition is true.
You should learn to indent the right amount and get rid of all that crazy white space. It makes it almost impossible to read. I had to go through and correct your indents and white space excess just to realize you had your brackets wrong.

Related

How can I capture if the user clicked a wrong button?

I made a game remember for the first fishes. I found a code like this. I also have wrong buttons.
Wrong buttons list:
pinkButton.addEventListener(MouseEvent.CLICK, pinkClick);
whiteButton.addEventListener(MouseEvent.CLICK, whiteClick);
greyButton.addEventListener(MouseEvent.CLICK, greyClick);
And I use this code
import flash.events.MouseEvent;
var checkString:String = "";
 
//Create event listeners and their functions.
YellowButton.addEventListener(MouseEvent.CLICK, yellowClick);
RedButton.addEventListener(MouseEvent.CLICK, redClick);
BlueButton.addEventListener(MouseEvent.CLICK, blueClick);
/*True choices*/
function yellowClick(evt:Event):void
{
//In each event listener function, add a letter or
//string to the checkString variable.
checkString += "y";
//Then, see if the string matches or not.
check();
}
function redClick(evt:Event):void
{
checkString += "r";
check();
}
function blueClick(evt:Event):void
{
checkString += "b";
check();
}
/*True choices*/
 
//If the proper sequence is red, yellow, blue, the string would read "ryb".
function check():void
{
if(checkString == "ryb")
{
//Clear the checkString for convenience before going on.
clearString();
//CODE TO GO TO NEW FRAME
gotoAndStop(3);
}
else
{
//Make sure the string is at least 3 characters long.
if(checkString.length >= 3)
{
clearString();
gotoAndStop(1);
}
}
}
function clearString():void
{
//You will want to have a function for clearing the string.
//This is especially useful if you have a button for "start over."
checkString = "";
}
 
if I click yellow, red, blue it works. How can I make wrong choices? Do I have to write a code for all possibilities? Player has 1 chance. For example if player clicked 2 false and 1 true button,or 2 true and 1 false, this results in a loss for the player.
Use an array of values. Like
var correctSequence:Array = ["r", "y", "b"];
then have a incrementing variable to give you control over traversing the array
var arrayPosition:int = 0;
and you need a variable to hold the Boolean value of whether or not there have been any wrong guesses:
var noneWrong:Boolean = true;
Then you could do something like
private function playerNextGuess(e:MouseEvent):void{
if (e.target._color == correctSequence[arrayPosition] && noneWrong == true){
arrayPosition++;
if (arrayPosition == 3){
playerWin();
arrayPosition = 0;
}
} else {
// put whatever logic you want for when the guess is wrong
noneWrong = false;
arrayPosition++;
if (arrayPosition == 3){
playerLose();
arrayPosition = 0;
}
}
This will make it so that 3 guesses are made before the results (right or wrong) are given to the player. But it won't tell the player which were right and which were wrong. If none are wrong, the win function is called. If any are wrong the lose function is called. Is that what you wanted?
Hopefully that gets you going in the right direction. Let me know if anything I wrote isn't abundantly clear.

Action script 3 walking animation

i need some help. im trying to make my character walk both direction(left and right) and an idle animation when standing still. i manage to make the character walk to the right and make the idle animation work. now if I copy the code from the right button to the left button, the walking animation gets stuck in the first frame on both direction. I tried to experiment with it but with no luck. im sorry if i sounded noob. i just started with studying programming.
here are the code that i used
RightBtn.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
function mouseDown(e:MouseEvent): void {
if(RightBtn){
isRight = true;
}
}
RightBtn.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
function mouseUp(e:MouseEvent): void {
if(RightBtn){
isRight = false;
}
}
stage.addEventListener(Event.ENTER_FRAME, loop);
function loop(Event){
if(isRight==true && mcPlayer.x < 750){
mcPlayer.x += 7;
mcPlayer.gotoAndStop (2);
mcPlayer.walkR.play ();
}
else{
mcPlayer.gotoAndStop (1)
mcPlayer.Idle.play ();
}
}
LeftBtn.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown2);
function mouseDown2(e:MouseEvent): void {
if(LeftBtn){
isLeft = true;
}
}
LeftBtn.addEventListener(MouseEvent.MOUSE_UP, mouseUp2);
function mouseUp2(e:MouseEvent): void {
if(LeftBtn){
isLeft = false;
}
}
stage.addEventListener(Event.ENTER_FRAME, loop2);
function loop2(Event){
if(isLeft==true && mcPlayer.x > 65){
mcPlayer.x -= 7;
mcPlayer.gotoAndStop (3);
mcPlayer.walkL.play ();
}
else{
mcPlayer.gotoAndStop (1)
mcPlayer.Idle.play ();
}
}
That's what you get from blatant copy&paste without learning the mechanics of how does it internally work. You set two listeners to stage, both altering mcPlayer regardless of whether it was already altered by the other one. So, you need to write both sets of code in one listener, and walk the code with your pen and paper to ensure that both isRight==true and isLeft==true branches work separately and don't interfere with each other. The proper condition statement should be like this:
if (isRight==true && mcPlayer.x < 750) {
// do a step right
} else if (isLeft==true && mcPlayer.x > 65){
// do a step left
} else {
// do idle animation
}
Your codes of initiating animation are correct themselves, they just get overridden by the listeners that are unaware of some other code altering mcPlayer.

flash as3 hitdetection function triggering other function

I am trying to code a script in which a movieclip drops a rope and catches fishes that follows it up if it touches it. here is the issue , i am using hitTestObject to detect collision . Ofcourse the problem is that i trigger the function when it touches but as soon as it doesnt touch the function for moving the movie starts so basically the fish goes up for few seconds and then starts moving straight again .
To try and fix that i tried to make a boolean variable which changes to true or false according to hit and accordingly makes the movieclip moves but also doesnt work because as soon as one mc is not touching the other it changes from true to false or 1 to 0 ..tried both (as in with boolean variable and Number variable) . Any help or putting me on the right direction would be highly appreciated . Thank you so much
// fish capture code
this.addEventListener(Event.ENTER_FRAME,handleCollision);
function handleCollision(e:Event):void
{
if (ropeHit.hitTestObject(fishy_1_a))
{
stopFish1();
trace(movefish1);
}
else
{
moveFish1();
}
}
//code enemy fishy
//fish 1 A
function moveFish1()
{
if (fishy_1_a.x < 800)
{
fishy_1_a.x += xSpeed;
}
else if (fishy_1_a.x >= 800)
{
fishy_1_a.x = -100;
}
}
function stopFish1()
{
fishy_1_a.y -= xSpeed;
}
Define some flag, that you can test:
function handleCollision(e:Event):void {
//Check if fishy is caught
if (!fishy_1_a.catched && ropeHit.hitTestObject(fishy_1_a)) {
//Change flag
fishy_1_a.catched = true;
trace("Gotcha!");
}
if (fishy_1_a.catched) {
stopFish1();
}else {
moveFish1();
}
}

How do you detect collisions between two arrays?

For future refrence this was the final code
for each (var bullet:Bullet in bulletList)
{
for each (var zombie:Zombie in zombieList)
{
if (zombie.hitTestObject(bullet))
{
stage.removeChild(bullet);
zombie.zombieShot(50);
}
}
}
Original Question Below
for each (var bullet:Bullet in bulletList)
{
if (zombieList.length > 0)
{
if (zombieList[h].hitTestObject(bullet))
{
bulletList[i].deleteBullet();
zombieList[h].zombieShot(50);
}
}
}
This is the code I have but it only detects the first zombie I spawn in, any help is appreciated.
if (countMePls<10)
{
countMePls++;
var zombie:Zombie = new Zombie(stage,Math.random() * stage.width,Math.random()*stage.height);
zombie.addEventListener(Event.REMOVED_FROM_STAGE,zombieRemoved,false,0,true);
zombieList.push(zombie);
stage.addChild(zombie);
}
and then...
function shootBullet():void
{
var bullet:Bullet = new Bullet(stage,Main.player.x,Main.player.y,Main.player.rotation - 90);
bullet.addEventListener(Event.REMOVED_FROM_STAGE,bulletRemoved,false,0,true);
bulletList.push(bullet);
stage.addChildAt(bullet,1);
}
this last bit is in Bullet.as
public function deleteBullet():void
{
this.parent.removeChild(this)
}
I think your issue comes from some basic confusion about for and for each. With for each you have no index variable, each iteration yields a new instance of the type in the collection which is referred to by the name you declare in the loop. In this case that is;
foreach (var bullet in bulletsList)
{
// do something with bullet
}
You probably actually want a nested loop, something that checks every bullet against each zombie to see if there was a hit, that would actually look like this;
foreach (var bullt in bulletsList)
{
foreach (var zombie in zombiesList)
{
if (zombie.hitTestObject(bullet))
{
bulletList.Remove(bullet);
zombie.zombieShot(50);
}
}
}
In your code you have the foreach loop giving you the current bullet object but then you never reference it within the loop, that doesn't make sense. This may not be exactly what you want but hopefully it will get you moving in the right direction. If you want to use those indexers then you need something like;
for (int i = 0; i < bulletsList.Length; i++)
{
for (int h = 0; h < zombiesList.Length; h++)
{
// do stuff with bulletsList[i] and zombiesList[h]
}
}
Note: this was originally tagged as C# and the code I've posted uses C# syntax. The explanation I've provided most likely applies either way, the OP's code doesn't really makes sense in any language I know of and the reasons are the same.

Error #1010 after splicing from array

I have an issue here. Every five seconds the spawnEnemies is fired. It creates a movieclip, sets it position and adds it to the stage and an array. In the function checkBullet I check if the bullet hits one of the enemies. If it does, the bullet and the enemy are removed from the stage, and the enemy is spliced from the array. But an error is thrown once I hit an enemy:
TypeError: Error #1010: A term is undefined and has no properties.
If I comment out the arrayEnemies.splice(i,1) line, it works fine but then it isn't removed from the array. This is in itself not an issue, but naturally I don't like to keep unnecessary data in my array. Any help on this?
function checkBullet(event:Event) {
if(stage.contains(mcBullet)) {
for(var i:int = 0; i < arrayEnemies.length; i++) {
if(arrayEnemies[i].hitTestPoint(mcBullet.x, mcBullet.y, true)) {
stage.removeChild(mcBullet);
this.removeChild(arrayEnemies[i]);
arrayEnemies.splice(i,1);
bulletOnStage = false;
}
}
if(mcBullet.x > 800) {
stage.removeChild(mcBullet);
bulletOnStage = false;
}
}
}
function spawnEnemies(event:TimerEvent) {
var enemie:MovieClip = new box_mc();
enemie.name = "mcBox" + event.currentTarget.currentCount;
enemie.x = 850;
enemie.y = Math.floor(Math.random()*(1+155)+255);
addChild(enemie);
arrayEnemies.push(enemie);
}
function moveEnemies(event:Event) {
for(var i:int = 0; i < arrayEnemies.length; i++) {
arrayEnemies[i].x -= 5;
}
}
This will be caused by working on an array that you are interating through, you should hold a ref to the stuff you want to remove then do it after the loop.
Your problem is that if the bullet hits two enemies, you try to remove it from the stage twice. This will throw an ArgumentError.
If you need to test against all enemies (assuming multiple enemies can be hit by the same bullet), you also need to decrement i when you remove an element from your enemy array.
function checkBullet(event:Event) {
if(stage.contains(mcBullet)) {
if(mcBullet.x > 800) {
stage.removeChild(mcBullet);
bulletOnStage = false;
}
for(var i:int = 0; i < arrayEnemies.length; i++) {
if(arrayEnemies[i].hitTestPoint(mcBullet.x, mcBullet.y, true)) {
if(stage.contains(mcBullet)){
stage.removeChild(mcBullet);
}
this.removeChild(arrayEnemies[i]);
arrayEnemies.splice(i,1);
bulletOnStage = false;
i--;
}
}
}
}
Bit of an older question but thought I'd throw in my answer too for anyone that might end up here.
Like Neil said, editing an array that you're itterating through (in this case arrayEnemies) can cause concurrent update problems.
My prefered solution is to use a seperate toRemove array and remove them after the update, for example:
var enemies:Array();
//Lets assume at some point this is populated with Enemy objects
function update():void
{
var toRemove:Array = new Array();
//May want to keep and clear an array instead to avoid creating a new one each update
foreach(var enemy:Enemy in enemies)
{
enemy.update();
if(enemy.markedForRemoval())
toRemove.push(enemy);
}
foreach(var enemy:Enemy in toRemove)
enemies.splice(enemies.indexOf(enemy), 1);
}