hitTestObject collision detection not working in as3! - actionscript-3

I am trying to create a platformer game and i am trying to make "player1" stop when it hits a "platform". here is my code so far,
gotoAndStop("gameStart");
import flash.display.MovieClip;
import flash.events.*;
import flash.ui.Keyboard;
import flash.ui.*;
import flash.utils.Timer;
import flash.events.TimerEvent;
player1.gotoAndStop("nothing");
//private var speed:Number = 0;
//private var maxspeed:Number = 4;
var myTimer:Timer = new Timer(10,0);
stage.focus = this;
player1.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
/*
myTimer.addEventListener(TimerEvent.TIMER,someFunction);
myTimer.start();
function someFunction(event:TimerEvent) {
player1.y += 2;
}
*/
function setup() {
stage.addEventListener(KeyboardEvent.KEY_DOWN, reactToArrowKeys);
}
setup();
function reactToArrowKeys(keyEvent:KeyboardEvent) {
if (keyEvent.keyCode == 37) {
if (player1.x > 0) {
player1.x -= 5;
}
} else if (keyEvent.keyCode == 39) {
if (player1.x < 700) {
player1.x += 5;
}
}
}
function enterFrameHandler(e:Event):void {
if (player1.hitTestObject(platform)) {
trace("hitting");
} else {
player1.y += 4;
}
}
however the hitTestObject function (enterFrameHandler) does not work properly and will always take the "else" route.
please help!

The code as posted works fine for me. I'd look for some other kind of silly mistake - for example, if you copied and pasted movie clips, you might have more than one clip on the stage named "platform", in which case your reference may not resolve to the one you intend. Or something else along those lines.
To track it down, try calling:
trace( player1.getBounds(stage) );
trace( platform.getBounds(stage) );
which will tell you where Flash thinks the bounding boxes of those clips are. My guess is that code will return something other than what you'd expect, and resolving that discrepancy will show where the bug is.

Related

Labyrinth/maze game

I'm creating a very simple game in Flash AS3 including labyrinth. Here's the code:
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
oseba.addEventListener(Event.ENTER_FRAME, premik);
oseba.addEventListener( Event.ENTER_FRAME, handleCollision)
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
var keys:Array = [];
function keyDownHandler(e:KeyboardEvent):void{
keys[e.keyCode] = true;
}
function keyUpHandler(e:KeyboardEvent):void{
keys[e.keyCode] = false;
}
function premik(e:Event):void{
if (keys[Keyboard.RIGHT]) {
oseba.x += 5;
}
if (keys[Keyboard.LEFT]) {
oseba.x -= 5;
}
if (keys[Keyboard.UP]) {
oseba.y -= 5;
}
if (keys[Keyboard.DOWN]) {
oseba.y += 5;
}
}
function handleCollision(e:Event ):void{
if(oseba.hitTestObject(nazaj)){
gotoAndPlay(2,"igra");
}
if(oseba.hitTestObject(gozd)){
gotoAndPlay(2);
}
I'd like to add collision detection, that will disallow my ''oseba'' that is walking around from walking over unmarked terrain. Below I've created a non visible MC ''potke''. I supposed the best way would be to calculate ''oseba'' 's next position and if it's on ''potke'' then ''oseba'' can't move there. I'm looking for suitable example of code, cos I've tried few different already, but non seems to work.
I'm also receiving the following error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at XYgame_fla::MainTimeline/handleCollision()
Everything seems to work fine otherwise, but this error keeps showing up.
I would try using nazaj.hitTestPoint(oseba.x, oseba,y, true) and put the EventListener to the stage to fix the error.

Actionscript 3.0, error with hitTestObject

I'm getting an error I can't seem to fix. I think I know kind of what is going on but I'm not sure enough to be able to fix it. I keep getting error
"TypeError: Error #2007: Parameter hitTestObject must be non-null.
at flash.display::DisplayObject/_hitTest()
at flash.display::DisplayObject/hitTestObject()"
Basically I fire an attack in my game. It hits an enemy and he is killed just fine. BUT, he has an animation as he dies that takes a couple seconds. It seems if I fire another attack during his animation, my attack IMMEDIATELY gives this error (before striking anything, that is). Once the animation is over, everything is fine again. Also, the game was working 100% fine before I put in this animation.
Here is my document class
package com.classes
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
public class DocumentClass extends MovieClip
{
// we need to keep track of our enemies.
public static var enemyList1:Array = new Array();
// moved stickobject1 to a class variable.
private var stickobject1:Stickman2;
public function DocumentClass() : void
{
//removed the var stickobject1:Stickman2 because we declared it above.
var bg1:background1 = new background1();
stage.addChild(bg1);
stickobject1 = new Stickman2(stage);
stage.addChild(stickobject1);
stickobject1.x=50;
stickobject1.y=300;
//running a loop now.... so we can keep creating enemies randomly.
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
//our loop function
private function loop(e:Event) : void
{
//run if condition is met.
if (Math.floor(Math.random() * 90) == 5)
{
//create our enemyObj1
var enemyObj1:Enemy1 = new Enemy1(stage, stickobject1);
//listen for enemyObj1 being removed from stage
enemyObj1.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemyObj1, false, 0, true);
//add our enemyObj1 to the enemyList1
enemyList1.push(enemyObj1);
stage.addChild(enemyObj1);
}
}
private function removeEnemyObj1(e:Event)
{
enemyList1.splice(enemyList1.indexOf(e.currentTarget), 1);
}
}
}
And here is my attack1 class
package com.classes {
import flash.display.MovieClip;
import flash.display.Stage;
import com.senocular.utils.KeyObject;
import flash.ui.Keyboard;
import flash.events.Event;
public class attack1 extends MovieClip {
private var stageRef:Stage;
private var bulletSpeed:Number = 16;
public function attack1 (stageRef:Stage, x:Number, y:Number) : void
{
this.stageRef = stageRef;
this.x = x;
this.y = y;
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event) : void
{
//move bullet up
x += bulletSpeed;
if (x > stageRef.stageWidth)
removeSelf();
for (var i:int = 0; i < DocumentClass.enemyList1.length; i++)
{
if (hitTestObject(DocumentClass.enemyList1[i].hit))
{
trace("hitEnemy");
removeSelf();
DocumentClass.enemyList1[i].takeHit();
}
}
}
private function removeSelf() : void
{
removeEventListener(Event.ENTER_FRAME, loop);
if (stageRef.contains(this))
stageRef.removeChild(this);
}
}
}
Don't think you should need any other of my classes to figure out what's going on, but let me know if you do! Thanks very much =)
You don't want to do a hit test against any object that may have been removed from the scene (or from the enemyList array). The extra condition added to attack1.loop's for loop should get rid of your error. A better fix is to splice out the items you remove, so they are never tested against in the loop.
The break line will make it stop trying to hit other enemies after the bullet is removed. If the line "DocumentClass.enemyList1[i].takeHit();" removes the item from the enemyList1, you need to make sure you use "i--;" at the bottom of the loop as well, if you plan on looping through the remainder of the enemies. "i--" or "break", you will probably need one of them in that loop.
Double check the order in which you are executing your removal methods. Sometimes it's better to flag the items for removal and remove them in a separate loop than to remove an item that may be needed later in the same loop.
for (var i:int = 0; i < DocumentClass.enemyList1.length; i++){
if(DocumentClass.enemyList1[i] && DocumentClass.enemyList1[i].hit){
if (hitTestObject(DocumentClass.enemyList1[i].hit)){
trace("hitEnemy");
removeSelf();
DocumentClass.enemyList1[i].takeHit();
break;
}
}
}
Not the correct solution in this question. You can always do != null in a conditional statement.
if(object!=null){
party.drink();
}

How to add a Timer in AS3

I was wondering how to add an ingame Timer in AS3, I made a health bar for enemy mobs and once mob is attacked, health bar is visible. I need to add piece of code which if Enemy was not attacked for 5 Seconds, healthBar.visible = false; but I have no idea how to deal with time in AS3
any ideas ?
My suggestions are as follows:
Assumed MouseClick is Ninja attacked hero. If you using a this code you need to create Class or fit type. I just written skeleton code.
Download Source
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
stage.addEventListener(MouseEvent.CLICK, onAttacked);
var isAttacked:Boolean;
var timer:Timer = new Timer(100,50);
var alphaCount:Number = 1.0;
timer.addEventListener(TimerEvent.TIMER, onTick);
function onAttacked(e:MouseEvent):void
{
isAttacked = true;
timer.start();
}
function onTick(e:TimerEvent):void
{
alphaCount = 1.0 - ( 2 * timer.currentCount ) / 100;
if(!isAttacked)
{
goFadeStatusBar();
}
else
{
restoreStatusBar();
alphaCount = 1.0;
timer.reset();
timer.start();
isAttacked = false;
}
}
function goFade():void
{
bar.alpha = alphaCount;
}
function restore():void
{
bar.alpha = 1;
}

FlashCS6 - Actionscript 3 - Loading SWFs - All playing but one

I'm just playing around trying to get a navigation bar to work and I'm having a spot of trouble. I've got a main.swf, and inside it is code to load in a circle.swf, square.swf and triangle.swf on their respective button clicks. The circle and square load in and play correctly, however the triangle loads, but doesn't play for some reason. The code, to my eye, is the same for all three, but only that one doesn't play.
Note sure where exactly the bug might be, but below it the code referring to the specific swfs. Let me know if it's helpful to see more though.
var _swfPathArr:Array = new Array("Subfolder/Circle.swf", "Subfolder/Subsubfolder/Square.swf", "Triangle.swf");
and
button_Circle.addEventListener(MouseEvent.CLICK, setContent);
button_Square.addEventListener(MouseEvent.CLICK, setContent);
button_Triangle.addEventListener(MouseEvent.CLICK, setContent);
And the method actually displaying and clearing the loaded swfs:
function setContent(event:MouseEvent):void
{
var _swfToAdd:MovieClip;
switch(event.target.name)
{
case "button_Circle":
_swfToAdd = _swfClipsArr[0];
gotoAndStop(2);
break;
case "button_Square":
_swfToAdd = _swfClipsArr[1];
gotoAndStop(3);
break;
case "button_Triangle":
_swfToAdd = _swfClipsArr[2];
gotoAndStop(4);
break;
}
Window_content.removeChildAt(Window_content.numChildren - 1);
Window_content.addChild(_swfToAdd);
}
Any help you can offer would be greatly appreciated.
EDIT:
All the code
import flash.display.MovieClip;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.IEventDispatcher;
import flash.events.ProgressEvent;
import flash.events.Event;
import flash.events.MouseEvent;
var _swfLoader:Loader;
var _swfRequest:URLRequest;
var _swfPathArr:Array = new Array("Subfolder/Circle.swf", "Subfolder/Subsubfolder/Square.swf", "Triangle.swf");
var _loadedSWFs:int;
var _swfClipsArr:Array = new Array();
var _swfTempClip:MovieClip;
startLoading(_swfPathArr);
function startLoading(pathArr:Array):void
{
_swfLoader = new Loader();
_swfRequest = new URLRequest();
addChildAt(_swfLoader, 0);
_loadedSWFs = 0;
loadSWF(pathArr[0]);
}
function loadSWF(path:String):void
{
setUpListeners(_swfLoader.contentLoaderInfo);
_swfRequest.url = path;
_swfLoader.load(_swfRequest);
}
function setUpListeners(dispatcher:IEventDispatcher):void
{
dispatcher.addEventListener(Event.COMPLETE, onSwfComplete);
dispatcher.addEventListener(ProgressEvent.PROGRESS, currentSwfProgress);
}
function currentSwfProgress(event:ProgressEvent):void
{
var _perc:int = (event.bytesLoaded / event.bytesTotal) * 100;
//swfPreloader.precentTF.text = _perc + "%";
}
function onSwfComplete(event:Event):void
{
event.target.removeEventListener(Event.COMPLETE, onSwfComplete);
event.target.removeEventListener(ProgressEvent.PROGRESS, currentSwfProgress);
_swfTempClip = event.target.content;
_swfTempClip.customID = _loadedSWFs;
_swfClipsArr.push(_swfTempClip);
if(_loadedSWFs < (_swfPathArr.length - 1))
{
_loadedSWFs++;
loadSWF(_swfPathArr[_loadedSWFs]);
}
else
{
_swfLoader.unloadAndStop();
_swfLoader = null;
onCompletePreloading();
}
}
function onCompletePreloading():void
{
button_Circle.addEventListener(MouseEvent.CLICK, setContent);
button_Square.addEventListener(MouseEvent.CLICK, setContent);
button_Triangle.addEventListener(MouseEvent.CLICK, setContent);
}
function setContent(event:MouseEvent):void
{
var _swfToAdd:MovieClip;
switch(event.target.name)
{
case "button_Circle":
_swfToAdd = _swfClipsArr[0];
gotoAndStop(2);
break;
case "button_Square":
_swfToAdd = _swfClipsArr[1];
gotoAndStop(3);
break;
case "button_Triangle":
_swfToAdd = _swfClipsArr[2];
gotoAndStop(4);
break;
}
Window_content.removeChildAt(Window_content.numChildren - 1);
Window_content.addChild(_swfToAdd);
//trace(_swfToAdd.customID);
}
stop();
So thanks to Cherniv suggesting to switch the order of the SWFs and see what happens, it seems the problem is related to the third element in the path array. Just need a pair of outside eyes to look over the code and they'll probably be able to spot some very obvious reason for my trouble, haha. If anybody can spot it, that would be greatly appreciated.

How to detect multiple key down event in as3?

I just got started learning AS3.
Let's say I have two textfields on my sprite.
I like to move textfield 1 when I press left or right arrow keys, but I also want to move textfield 2 when I press space while textfield 1 is moving like...an airplay game (you can shoot a missile while you're moving).
I really like to post my source code...but I actually have no idea where to begin.
the following code moves textfield 1 when I press arrow keys...
my code snippet:
private function keyHandler(event:KeyboardEvent):void
{
switch(event.keyCode)
{
case 38:
this._txt.y -= 10;
break;
case 40:
this._txt.y += 10;
break;
case 39:
this._txt.x += 10;
break;
case 37:
this._txt.x -= 10;
break;
}
}
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
/**
* ...
* #author www0z0k
*/
public class KeyExample extends Sprite {
private var _theyArePressed:Object = { };
public function KeyExample() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onUp);
}
private function onUp(e:KeyboardEvent):void {
_theyArePressed[e.keyCode] = false;
}
private function onDown(e:KeyboardEvent):void {
_theyArePressed[e.keyCode] = true;
if (_theyArePressed[Keyboard.SPACE] && _theyArePressed[Keyboard.UP]) {
//do anything
}
}
}
}
but keep in mind that that AFAIK keyboards can handle limited quantity of keys pressed at the same time, depending on the hardware