I want to stop the movieclips movement when it hits a wall (another movieclip).
The example below works, but after the collision the movieclip 'blocks' all movement to the left...
My question to you is, is this a good way and why isn't it working well?
There will be something wrong in this code, but i'm learning.
For now the example with the leftArrow key;
variables to check the key, if it's hitting the walls and if it's moving or not:
var leftArrow:Boolean;
var speed:int = 10;
var hitting:Boolean;
var ismoving:Boolean;
event listeners for the keys/movement and detecting collision:
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.ENTER_FRAME, walking);
stage.addEventListener(Event.ENTER_FRAME, detectHit);
detecting collision function:
function detectHit(e:Event) :void
{
if(char.hitTestObject(bounds))
{
hitting = true;
}
}
function to the left arrow key:
function keyPressed(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
leftArrow = true;
}
}
function keyReleased(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
leftArrow = false;
}
}
And the reason it's not working is probably here, but I don't understand why not:
function walking(event:Event):void {
if (rightArrow) {
char.x += speed;
}
if (leftArrow && ! hitting) {
char.x -= speed;
}
else
{
ismoving = false
}
if (leftArrow && ! hitting)
char will move if hitting is false. When char.hitTestObject(bounds) is true you are setting hitting to true. You are not setting hitting again to false anywhere. That's why once left wall is hit it stops left movement permanently. You need to figure out suitable condition to set hitting to false again.
Adding an else branch in detectHit should solve the problem.
function detectHit(e:Event):void {
if(char.hitTestObject(bounds))
{
hitting = true;
} else {
hitting = false; // add this
}
}
Allthough Taskinoor's method should work, I would suggest another way to do your hittests.
Since you probably are creating a game (character and bounds), you will have more than one bound. In that case, I would strongly suggest bitmap-hittesting. This way, you can create all your bounds in one movieclip and test for a hit.
I will explain this by using the example of a maze. The maze would then be some lines in a movieclip, randomly put together. If you use HitTestObject and you aren't hitting one of the lines, but your character is over the movieclip, hitTestObject will return true, even though you are not hitting a wall. By using bitmapHitTesting, you can overcome this problem (BitmapHitTest takes transparant pixels into account, whereas hitTestObject does not).
Below you can find an example of how to do bitmapHitTesting. Creating the bitmaps in this function is not necesarry if they do not change shape. In that case, I would suggest placing the code for the bitmapdata in a added_to_stage-method.
private var _previousX:int;
private var _previousY:int;
private var _bmpd:BitmapData ;
private var _physicalBitmapData:BitmapData;
private function walkAround(e:Event):void
{
var _xTo:int = //Calculate x-to-position;
var _yTo:int = //Calculate y-to-position;
//If your character doesn't change shape, you don't have to recalculate this bitmapData over and over.
//I suggest placing it in a ADDED_TO_STAGE-Event in that case.
_bmpd = new BitmapData(char.width, char.height, true, 0);
_bmpd.draw(char);
//If your bounds are static, you don't have to recalculate this bitmapData over and over.
//I suggest placing it in a ADDED_TO_STAGE-Event in that case.
_physicalBitmapData = new BitmapData(bounds.width, bounds.height, true, 0);
_bmpd.draw(bounds);
//The below line is the actual hittest
if(_physicalBitmapData.hitTest(new Point(0, 0), 255, _bmpd, new Point(char.x, char.y), 255))
{
char.x = _previousX;
char.y = _previousY;
}
else
{
char.x = _xTo;
char.y = _yTo;
}
_previousX = char.x;
_previousY = char.y;
}
Look at my hint,
function loop(Event)
{
if(isHit==false)
{
if(isRight==true){head_mc.x+=1}
if(isLeft==true){head_mc.x-=1}
if(isUp==true){head_mc.y-=1}
if(isDown==true){head_mc.y+=1}
}
if(head_mc.hitTestObject(build_mc))
{
isHit=true;
if(isRight==true){head_mc.x-=1}
if(isLeft==true){head_mc.x+=1}
if(isUp==true){head_mc.y+=1}
if(isDown==true){head_mc.y-=1}
}
else
{
isHit=false;
}
}
I use step back to opposite direction instead.
Related
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.
I am creating a game that a sheep need to jump or crouch to avoid obstacles.
I had create 2 types of obstacles but they come in a constant speed.
Sometimes the 2 obstacles come together make it impossible to avoid. Is there any way to change this?
Can I make the 2 obstacles come in randomly in a random speed?Here is my code.`
hole_mc.visible = false;
bird_mc.visible = false;
playhotarea_btn.addEventListener(MouseEvent.CLICK, removeInstructionBox);
function removeInstructionBox(event:MouseEvent):void
{
playhotarea_btn.removeEventListener(MouseEvent.CLICK, removeInstructionBox);
instructionbox_mc.visible = false;
instructiontext_mc.visible = false;
playbtn_mc.visible = false;
playbtntext_mc.visible = false;
sheep_mc.sheepIN_mc.visible = false;
sheep_mc.gotoAndPlay("sheepwalk");
treebg_mc.gotoAndPlay("bgloop");
hole_mc.visible = true;
bird_mc.visible = true;
timer.start();
}
hole_mc.addEventListener(Event.ENTER_FRAME, holeMove);
function holeMove(event:Event):void {
if (hole_mc.x>= -200) {
hole_mc.x -=7;
}else{
hole_mc.x=1080;
trace("hole loops");
}
}
bird_mc.addEventListener(Event.ENTER_FRAME, birdMove);
function birdMove(event:Event):void {
if (bird_mc.x>= -200) {
bird_mc.x -=10;
}else{
bird_mc.x=1080;
trace("bird loops");
}
}
stage.addEventListener(Event.ENTER_FRAME, hitHole);
function hitHole(event:Event):void{
if (sheep_mc.hitTestObject(hole_mc)){
gotoAndStop("GameOver");
hole_mc.removeEventListener(Event.ENTER_FRAME, holeMove);
stage.removeEventListener(Event.ENTER_FRAME, hitHole);
bird_mc.removeEventListener(Event.ENTER_FRAME, birdMove);
stage.removeEventListener(Event.ENTER_FRAME, hitBird);
}
}
stage.addEventListener(Event.ENTER_FRAME, hitBird);
function hitBird(event:Event):void{
if (sheep_mc.hitTestObject(bird_mc)){
gotoAndStop("GameOver");
bird_mc.removeEventListener(Event.ENTER_FRAME, birdMove);
stage.removeEventListener(Event.ENTER_FRAME, hitBird);
hole_mc.removeEventListener(Event.ENTER_FRAME, holeMove);
stage.removeEventListener(Event.ENTER_FRAME, hitHole);
}
}
var currentSecond:Number = 0;
var delay:Number = 1000;
var timer:Timer = new Timer(delay);
timer.addEventListener(TimerEvent.TIMER, timerEventHandler);
function timerEventHandler(event:TimerEvent):void
{
currentSecond++;
trace(currentSecond);
score_txt.text = String(currentSecond + " s");
}
`
You can always avoid spawning things in the same place by testing for "collision" before you create (or in your case, move) the new object. You should do the testing in whatever class has a reference to all the objects on the screen. In this case, the class you posted has references to the hole and bird, which are the two objects you want to NOT have the same x value.
Try something along the lines of:
function birdMove(event:Event):void {
if (bird_mc.x>= -200) {
bird_mc.x -=10;
}else{
if(hole_mc.x > 1000){ // See notes below
bird_mc.x=1080;
trace("bird loops");
}}}
I put 1000 under the assumption that you would want a little bit of space between the two obstacles. If you're only worried about them being EXACTLY on top of each other, then you can just use if hole_mc.x = 1080. But by using > some number, you can guarantee a little bit of room between them.
You should add a similar line to the hole mover as well so that it doesn't matter which one gets called first. They both check before they respawn.
I have written a code to move a MovieClip on pressing space bar. So if someone presses space bar ..it activates a boolean variable from false to true and if its true the object moves ..but its not working. can some one please help. Thank you
var rope = MovieClip(this.root).boat_mc.rope_mc.fishyrope_mc.hitbox_mc;
var ropeMove:Boolean = false;
stage.addEventListener(Event.ENTER_FRAME, ropeCode);
stage.addEventListener(KeyboardEvent.KEY_UP, onSpacebarUp);
function onSpacebarUp(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.SPACE)
ropeMove = !ropeMove; // toggles ropeMove (i.e. if it's true, sets it to false, and vice versa)
}
function ropeCode(e:Event):void
{
// move the rope
if( ropeMove )
{
rope.y += xSpeed;
// stop moving if we've gone too far
if( rope.y > 600.0 )
{
rope.y = 600.0;
ropeMove = false;
}
}
}
This should work
var ropemove:Boolean = true;
var xSpeed = 5;
var once:Boolean=false;
stage.addEventListener(Event.ENTER_FRAME,ropeCode);
stage.addEventListener(KeyboardEvent.KEY_UP,onSpacebarUp);
function onSpacebarUp(e:KeyboardEvent):void
{
if (e.keyCode == 32)
{
if (ropemove==true)
{
if(once==false)
{
ropemove = false;
once=true
}
}
if(ropemove==false)
{
ropemove==true
}
}
if (rope.x >= stage.stageWidth )
{
ropemove = false;
}
trace(ropemove)
}
function ropeCode(e:Event):void
{
if (ropemove == true)
{
rope.x += xSpeed;
}
}
Two problems I can spot in your code:
1.) Everything is inside your Event.ENTER_FRAME event handler. This means every frame, that code is going to be run: including where you're adding a keyboard event listener. After 1 second, (assuming you are running at 30 fps) onSpacebarUp() will fire 30 times when you press space, and keeps increasing. Probably not a good idea, pretty sure you only want to add this once.
2.) The part where the boolean value will cause your movieclip to move is in a method: dropRope(). But this is not called anywhere, so it is actually not doing anything. Also may not need the event argument (the e:event) part, as you're not using it nor is it being called from an event.
BennettLiam's code should do something closer to what you want, I'm just adding this answer as an explanation for why your code isn't working. In their answer, they've fixed the above problems I mentioned: moved the event listener code for the keyboard outside of the event frame handler loop so it is only added once, and changed the enter frame event handler to call dropRope() o every frame, so that it is doing something.
var rope = MovieClip(this.root).boat_mc.rope_mc.fishyrope_mc.hitbox_mc;
var ropeMove:Boolean = false;
stage.addEventListener(Event.ENTER_FRAME, ropeCode);
stage.addEventListener(KeyboardEvent.KEY_UP, onSpacebarUp);
function onSpacebarUp(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.SPACE)
ropeMove = !ropeMove; // toggles ropeMove (i.e. if it's true, sets it to false, and vice versa)
}
function ropeCode(e:Event):void
{
// move the rope
if( ropeMove )
{
rope.y += xSpeed;
// stop moving if we've gone too far
if( rope.y > 600.0 )
{
rope.y = 600.0;
ropeMove = false;
}
}
}
I'm very new to coding and am having trouble finishing the last little bit of a mini game type project for school.
So this is a draft of what the program looks like so far: http://aaronmillard.com/dir/wp-content/uploads/2013/08/Google-Doodle_Roomba.swf
Now what I want the program to do is "vacuum" up the google when the roomba drives over it. The easiest way to achieve this (I think) is to have an exact replica of the carpet layer without the google logo beneath the carpet layer with the google logo. So I would need to code something like "when the object(roomba) passes over object(carpetwithgooglelogo) make object(carpetwithgooglelogo) have 0 opacity." I just can't figure out how to say that in code.
The code as of right now look like this:
// Assign 4 booleans for the 4 arrow keys
var keyUp = false;
var keyDown = false;
var keyLeft = false;
var keyRight = false;
// Add the keyboard event (KEY_DOWN) on the stage
stage.addEventListener(KeyboardEvent.KEY_DOWN, pressKey);
function pressKey(pEvent)
{
// If an arrow key is down, switch the value to true to the assigned variable
if (pEvent.keyCode == 38)
{
keyUp = true;
}
else if (pEvent.keyCode == 40)
{
keyDown = true;
}
else if (pEvent.keyCode == 37)
{
keyLeft = true;
}
else if (pEvent.keyCode == 39)
{
keyRight = true;
}
}
// Add the keyboard event (KEY_UP) on the stage
stage.addEventListener(KeyboardEvent.KEY_UP, releaseKey);
function releaseKey(pEvent)
{
// If the arrow key is up, switch the value to false to the assigned variable
if (pEvent.keyCode == 38)
{
keyUp = false;
}
else if (pEvent.keyCode == 40)
{
keyDown = false;
}
else if (pEvent.keyCode == 37)
{
keyLeft = false;
}
else if (pEvent.keyCode == 39)
{
keyRight = false;
}
}
// Set the velocity of the object
var speed = 4;
// And the rotation speed
var rotationSpeed = 6;
// Add an enter frame event on the moving object
myCircle.addEventListener(Event.ENTER_FRAME, circleEnterFrame);
function circleEnterFrame(pEvent)
{
// Set the default velocity to 0 if no key is pressed
var velocity = 0;
if (keyUp)
{
// If the key up is pressed set the new velocity to the speed value
velocity = speed;
}
if (keyDown)
{
// If the key down is pressed set the new velocity to the half speed value
velocity = -speed/2;
}
if (keyLeft)
{
// rotate the object
pEvent.currentTarget.rotation -= rotationSpeed;
}
if (keyRight)
{
// rotate the object
pEvent.currentTarget.rotation += rotationSpeed;
}
// Convert the degreeAngle to the radian angle
var angleRadian = pEvent.currentTarget.rotation / 180 * Math.PI;
// Move the object with the radian angle and the object speed
pEvent.currentTarget.x += Math.cos(angleRadian) * velocity;
pEvent.currentTarget.y += Math.sin(angleRadian) * velocity;
}
Any help would be very much appreciated! Thanks!
The easiest way is to do something like this:
if( roomba.hitTestObject(google)){
google.alpha = 0;
}
You'll have to check this on every frame using an ENTER_FRAME event.
If this is confusing tell me in the comments and I will clarify with more code.
This is my fist time ever needing to use this for one of my games. I want to have the character jump. I have been trying to get this result for about an hour, but with no luck =( I am using AS3, and flash CS5.5. So far all my code does is make the character go left, and right based on keyboard input. Could someone please help?
Here is my code so far:
public class Dodgeball extends MovieClip
{
public var character:Character;
public var rightDown:Boolean = false;
public var leftDown:Boolean = false;
public var speed:Number = 3;
public var timer:Timer;
public function Dodgeball()
{
character= new Character();
addChild(character);
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, MyKeyUp);
timer = new Timer(24);
timer.addEventListener(TimerEvent.TIMER, moveClip);
timer.start();
}
public function myKeyDown(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.RIGHT)
{
rightDown = true;
if(character.currentLabel != "walkingRight")
{
character.gotoAndStop ("walkingRight");
}
}
if (event.keyCode == Keyboard.LEFT)
{
leftDown = true;
if (character.currentLabel != "backingUp")
{
character.gotoAndStop("backingUp");
}
}
}
public function MyKeyUp(event:KeyboardEvent):void
{
if(event.keyCode == Keyboard.RIGHT)
{
character.gotoAndStop("standing");
rightDown = false;
}
if (event.keyCode == Keyboard.LEFT)
{
character.gotoAndStop("standingLeft");
leftDown = false;
}
}
public function moveClip(event:TimerEvent):void
{
if (rightDown)
{
character.x += speed;
}
if (leftDown)
{
character.x -=speed;
}
event.updateAfterEvent();
}
}
}
One method you can try is found here: http://www.actionscript.org/forums/showthread.php3?t=256009 Like your speed variable, grav determines the vertical position of the character.
var grav:Number = 10;
var jumping:Boolean = false;
var jumpPow:Number = 0;
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(Event.ENTER_FRAME, update);
function onKeyDown(evt:KeyboardEvent):void
{
if(evt.keyCode == Keyboard.UP)
{
if(jumping != true)
{
jumpPow = -50;
jumping = true;
}
}
}
function update(evt:Event):void
{
if(jumping)
{
player_mc.y += jumpPow;
jumpPow += grav;
if(player_mc.y >= stage.stageHeight)
{
jumping = false;
player_mc.y = stage.stageHeight;
}
}
}
Edit: Jason's method is fine, but I'm not sure if it would be useful if you plan to have some kind of collision detection.
What I would do is create a motion tween of the character jumping. then call gotoAndPlay on that frame, and on the last frame of the tween put a stop, or a gotoAndStop on the "stationary" frame, or whatever frame represents a neutral position.
if (event.keyCode == Keyboard.SHIFT)
{
character.gotoAndPlay("simpleJump");
jumpDown = false;
}
This will give you the greatest animation control over the look and feel. You could also do it programmatically, but personally, I recommend against it. It will take less time to set it up, and you can tweak and refine the jump animations later. You could make several types of jump animations based on object near the target etc.
I would also change this stuff:
if(character.currentLabel != "walkingRight")
By defining a new function where you have all the rules for when and where something can be done, so that in your control logic, you just call
if(characterCan(character,"walkright")) ...
Where characterCan(String) is a method that check if this is possible. For instance, if you are jumping and shooting, you obviously cannot walk right, so in the end, you will have to start adding pieces of logic into those if statements and it's gonna become a cluttered mess.
A very simple approach is to have a vertical speed as well as a horizontal speed.
When the user presses "UP" or "JUMP", set y speed to a negative value and update it in your movieClip function. When the character gets to a certain height, reverse the speed.
Using gravity and acceleration looks better but this is a really good place to start. Look into kinematic equations to see how you would make the character accelerate.
public var originalY;
public function myKeyDown(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.UP && vSpeed == 0)
{
originalY = character.y;
ySpeed = -1;
}
}
public function moveClip(event:TimerEvent):void
{
if (vSpeed != 0)
{
character.y += vSpeed;
/* make the character fall down after reaching max jump height */
if(originalY - character.y > jumpHeight) {
vSpeed = vSpeed * -1;
}
/* level the character after he's hit the ground (so he doesn't go through) */
else if(character.y >= originalY) {
character.y = originalY;
vSpeed = 0;
}
}
}