AS3 AI barrier detection and movement - actionscript-3

I'm using flash CC for school and i am making a top down RPG which i am making using action script 3.
the problem that i am having is multi layered; i need the AI i made to detect the set boundaries, and i need them to change direction when they hit these boundaries. at the moment i have used trace functions to find out when the AI is hitting the boundaries, so i know that that is working. however then it doesn't run the code after that. the map at the moment is a maze so the barriers are a movie clip that have rectangles going over the walls within the maze. it works for the player that the user controls so why won't it work here? below is the code for the AI movement:
switch (guyFacing) { // which way the AI has turned (left, right, up, down) (this is randomly generated below
case 0:
OverworldMC.guyMC.gotoAndStop("walk back frame");
OverworldMC.guyMC.y -= guySpeed;
break;
case 1:
OverworldMC.guyMC.gotoAndStop("walk front frame");
OverworldMC.guyMC.y += guySpeed;
break;
case 2:
OverworldMC.guyMC.gotoAndStop("walk left frame");
OverworldMC.guyMC.x -= guySpeed;
break;
case 3:
OverworldMC.guyMC.gotoAndStop("walk right frame");
OverworldMC.guyMC.x += guySpeed;
break;
}
guyTimer++; //duration that the AI is moving around the screen
} else {
guyWalkDur = Math.random() * 75;
guyFacing = Math.floor(Math.random() * 4);
guyTimer = 0;
}
}
if (OverworldMC.collisionMC.hitTestPoint(OverworldMC.guyMC.x + GleftBumpPoint.x, OverworldMC.guyMC.y + GleftBumpPoint.y, true)) {
trace("GleftBumping");
GleftBumping = true;
} else {
GleftBumping = false;
}
if (OverworldMC.collisionMC.hitTestPoint(OverworldMC.guyMC.x + GrightBumpPoint.x, OverworldMC.guyMC.y + GrightBumpPoint.y, true)) {
trace("GrightBumping");
GrightBumping = true;
} else {
GrightBumping = false;
}
if (OverworldMC.collisionMC.hitTestPoint(OverworldMC.guyMC.x + GupBumpPoint.x, OverworldMC.guyMC.y + GupBumpPoint.y, true)) {
trace("GupBumping");
GupBumping = true;
} else {
GupBumping = false;
}
if (OverworldMC.collisionMC.hitTestPoint(OverworldMC.guyMC.x + GdownBumpPoint.x, OverworldMC.guyMC.y + GdownBumpPoint.y, true)) {
trace("GdownBumping");
GdownBumping = true;
} else {
GdownBumping = false;
}
if (GleftBumping) {
OverworldMC.guyMC.gotoAndStop("walk right frame");
OverworldMC.guyMC.x -= guySpeed;
trace("hitting is true");
}
if (GrightBumping) {
OverworldMC.guyMC.gotoAndStop("walk left frame");
OverworldMC.guyMC.x += guySpeed;
}
if (GupBumping) {
OverworldMC.guyMC.gotoAndStop("walk front frame");
OverworldMC.guyMC.y -= guySpeed;
}
if (GdownBumping) {
OverworldMC.guyMC.gotoAndStop("walk back frame");
OverworldMC.guyMC.y += guySpeed;
}
The aim of this code is to randomly generate an action (which it does), detect when it is hitting the barrier and then act according to how it is interacting with the barrier only i am having some trouble with the last part. Any and all help is appreciated.
Regards.

Related

AS3: Swipe Gesture With Velocity

So I would like to add velocity to my swipe gesture. Currently I have it moving 10 px on swipe, but I want it to move with a velocity so the user can toss the object around on the screen. Here's the code I am currently using with the object moving the 10 px.
function onSwipe (e:TransformGestureEvent):void{
player_mc.gotoAndStop(5);
if (e.offsetX == 1) {
//User swiped towards right
player_mc.x += 10;
}
if (e.offsetX == -1) {
//User swiped towards left
player_mc.x -= 10;
}
if (e.offsetY == 1) {
//User swiped towards bottom
player_mc.y += 10;
}
if (e.offsetY == -1) {
//User swiped towards top
player_mc.y -= 10;
}
if(collision(player_mc.cp, level_mc))
{
player_mc.x = player_mc.prevX;
player_mc.y = player_mc.prevY;
}
}
Thanks for the help
Here is a way you can do this: (you'll want to swap the mouse events for touch events if using on mobile)
player_mc.addEventListener(MouseEvent.MOUSE_DOWN,startSwipe);
player_mc.addEventListener(MouseEvent.MOUSE_UP,endSwipe);
var velocity:Point = new Point(); //this stores the current velocity of the object
var previous:Point = new Point(); //this stores the previous frames x/y of the object.
var isDragging:Boolean = false;
var friction:Number = .85; //this how quickly to slow down the object once the mouse is released - smaller the number (must be less than 1) the quicker the object will slow/stop
function startSwipe(e){
isDragging = true;
player_mc.startDrag(false);
this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
}
function enterFrameHandler(e):void {
if(isDragging){
velocity.x += player_mc.x - previous.x; //we're adding the new velocity to the old one, then dividing in half to average the value - this makes it seem smoother
velocity.y += player_mc.y - previous.y;
velocity.x *= .5; //dividing in half
velocity.y *= .5;
previous.x = player_mc.x;
previous.y = player_mc.y;
}else{
velocity.x *= friction; //gradually slow down the object
velocity.y *= friction;
player_mc.x += velocity.x;
player_mc.y += velocity.y;
if(velocity.x < .05 && velocity.y < .05){ //once it gets slow enough, stop the enter frame handler
this.removeEventListener(Event.ENTER_FRAME,enterFrameHandler);
}
}
trace(velocity);
}
function endSwipe(e){
player_mc.stopDrag();
isDragging = false;
}

charging Timer doesn't quite work?

I'm writing a game where I want the character to jump after holding the spacebar to charge their jump up for a bit and then the charge will get added into the jump afterwards.
However, the code that I currently have going only works around 50% of the time, and will almost indefinitely not work if the player is holding a directional movement button down at the same time.
function greenTimerHandler(e:TimerEvent){
if(spacePressed&&downBumping){
charge += 3;
if(charge >= 50){
charge = 50;
}
} else if(!spacePressed&& downBumping) {
greenSlimeJump(charge);
greenSlimeTimer.stop();
}
}
//And the jump function
function greenSlimeJump(greenCharge){
ySpeed = greenCharge * -1.5
slimeAmt -= Math.floor(greenCharge * 0.25);
charge = 0;
}
the downBumping is just a boolean collision value based on a hitTestPoint for the bottom of the player...
Is there any way that I can make it so that it actually runs the jump function more than it currently does? It will even keep the charge value for the next time it tries to jump and the slimeAmt value is never subtracted because the code just seems to completely skip the green jump function altogether.
Heres the downBumping code:
if(back.collisions.hitTestPoint(player.x + downBumpPoint.x, player.y +
downBumpPoint.y, true)){
downBumping = true;
} else {
downBumping = false;
}
and heres the timer/ space pressed:
if(e.keyCode == 32 && slimeAction){
spacePressed = true;
if(slimeType == 1 && downBumping){
greenSlimeTimer.start();
}
}

[AS3]Collision with walls using hitTestObject

So I am currently trying to do a game which is almost like a maze.
The problem is with the wall collision, once the character hits a wall, I can't get him out anymore, he gets "stuck" no matter what direction I try to take him after the collision.
One of the solutions I was thinking would be to whenever the character hits the wall, to "back him up", so that there is no more collision detected. However, when I do that, he goes through the wall in a strange way.
Here is my code so you guys can have an idea of what I'm doing:
function keyPressed(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
leftArrow = true;
if(char.hitTestObject(test))
{
leftHit= true;
} else {
leftHit = false;
}
}
if (event.keyCode == Keyboard.RIGHT)
{
rightArrow = true;
if(char.hitTestObject(test))
{
rightHit= true;
} else {
rightHit = false;
}
}
}
function keyReleased(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
leftArrow = false;
}
if (event.keyCode == Keyboard.RIGHT)
{
rightArrow = false;
}
}
function walking(event:Event):void {
if (rightArrow) {
if(rightHit)
char.x -= speed;
else
char.x += speed;
}
if (leftArrow) {
if(leftHit)
char.x += speed;
else
char.x -= speed;
}
}
A big part of this code I actually got from another person asking the same question. Even doing what was suggested in the other topic, the problem still remains.
Thank you very much for any help!
As requested, here is my solution:
if (rightArrow) {
if (!test.hitTestPoint(MovieClip(root).char.x+speed, MovieClip(root).char.y, true))
{
MovieClip(root).char.x += speed;
x = x-speed; //moving the background
}
}
if (leftArrow) {
if (!test.hitTestPoint(MovieClip(root).char.x-speed, MovieClip(root).char.y, true))
{
MovieClip(root).char.x -= speed;
x = x+speed; //moving the background
}
}
if (upArrow) {
if (!test.hitTestPoint(MovieClip(root).char.x, MovieClip(root).char.y-speed, true))
{
MovieClip(root).char.y -= speed;
y = y+speed; //moving the background
}
}
if (downArrow) {
if (!test.hitTestPoint(MovieClip(root).char.x, MovieClip(root).char.y+speed, true))
{
MovieClip(root).char.y += speed;
y = y-speed; //moving the background
}
}
It's been a while so some of this stuff I really don't remember, but from what I can see, I check if adding the speed of my character will make it become collided with the wall. If that happens, I do not move the character even if I do seemingly have enough space. I think that is pretty much it.
Hope it helps.

How to call AS3 Switch

I am struggling a bit with my switch statement (I've never used switch before). I have a hit test for when my object reaches the top or bottom of the stage. When this happens, I want to switch states (the game in question is a simple platformer that allows the player to switch the gravity when they hit a new surface. Below is my current code:
{
...
if(player.hitTestObject(bottom)) {
//Switch state to normal
}
if(player.hitTestObject(top)) {
//Switch state to inverted
}
}
switch (myGrav){
case "NORMAL":
trace("Normal")
player.gotoAndPlay(1);
oktoJump = false;
player.y = 376.5;
case "INVERTED":
trace("Inverted")
player.gotoAndPlay(8);
oktoJump = false;
player.y = 12;
}
Thanks!
Cases within your switch statement are missing a break; therefore, code will continue to execute through the switch statement.
This should be:
var myGrav:String = "NORMAL";
if (player.hitTestObject(bottom))
myGrav = "NORMAL";
if (player.hitTestObject(top))
myGrav = "INVERTED";
switch (myGrav)
{
case "NORMAL":
trace("Normal")
player.gotoAndPlay(1);
oktoJump = false;
player.y = 376.5;
break;
case "INVERTED":
trace("Inverted")
player.gotoAndPlay(8);
oktoJump = false;
player.y = 12;
break;
}
I prefer less variables when I can get away with it.
switch (true){
case (player.hitTestObject(bottom)):
trace("Normal")
player.gotoAndPlay(1);
oktoJump = false;
player.y = 376.5;
break;
case (player.hitTestObject(top)):
trace("Inverted")
player.gotoAndPlay(8);
oktoJump = false;
player.y = 12;
break;
}

ActionScript 3 - Walls don't collide properly

For several weeks I'm been trying to make my topdown game. It went well for some time, but then at some point I wanted to create a scrolling map with walls everywhere. Now, to make it easy to create the map (and add more later) I made a class called "Wall" which I will hit test. This works, when it hits, the map must stop scrolling. It does, so good so far.
Now, when the player moves away from the object, I want the map to be able to scroll again, this works too, but now the player can't move to the side the player came from. I know this is because I need to define the sides, where the player enters, in order tell the game which movement must be set to zero at that point.
You can see the code here:
public function AddWalls(player:MovieClip)
{
WallObjects = new Array();
for (var i:int = 0; i < this.numChildren; i++)
{
var mc = this.getChildAt(i);
if (mc is Wall)
{
var wallobj:Object = new Object();
wallobj.mc = mc;
wallobj.leftside = mc.x;
wallobj.rightside = mc.x + mc.width;
wallobj.topside = mc.y;
wallobj.bottomside = mc.y + mc.height;
wallobj.width = mc.width;
wallobj.height = mc.height;
WallObjects.push(wallobj);
}
}
}
public function EnableCollisionWithWalls():void
{
for (var k:int = 0; k < WallObjects.length; k++)
{
//if (player.y > WallObjects[k].topside && player.y < WallObjects[k].bottomside && player.x > WallObjects[k].leftside && player.x < WallObjects[k].rightside)
if (player.hitTestObject(WallObjects[k].mc))
{
if (player.x > WallObjects[k].leftside && player.x < WallObjects[k].leftside+15)
{
Lefthit = true;
trace(DebugVar);
DebugVar++;
player.x = WallObjects[k].leftside;
Scroll_x = 0;
}
else
if ( player.x < WallObjects[k].leftside -1 || (player.y > WallObjects[k].leftside ))
{
Lefthit = false;
}
if (player.hitTestObject(derp))
{
Lefthit = false;
}
}
}
}
public function EnableMovement():void
{
map.x += Scroll_x;
map.y += Scroll_y;
for (var i:int = 0; i < this.numChildren; i++)
{
var mc = this.getChildAt(i);
if (mc is Wall)
{
mc.x += Scroll_x;
mc.y += Scroll_y;
}
}
}
public function MovementKeysDown(move:KeyboardEvent):void
{
var Speed:int = -5;
switch (move.keyCode)
{
case 37: // venstre knap
Scroll_x = -Speed;
break;
case 38: // op
Scroll_y = -Speed;
break;
case 39: // højre knap
Scroll_x = Speed;
if (Lefthit)
{
Scroll_x = 0;
}
break;
case 40: // ned
Scroll_y = Speed;
break;
default:
}
}
public function MovementKeysUp(move:KeyboardEvent):void
{
switch (move.keyCode)
{
case 37:
Scroll_x = 0;
break;
case 38:
Scroll_y = 0;
break;
case 39:
Scroll_x = 0;
break;
case 40:
Scroll_y = 0;
break;
default:
}
}
Might be some syntax errors (since I removed some code in this editor).
You can see the current version here.
In this version the scroll keeps on going. I did come up with a "fix" for it, by check if the player was 1 pixel away from the movieclip, inside the hit test (which for some reason works, which I guess it shouldn't since it doesn't hit anymore) and then setting the Lefthit to false. However this is not a good solution and if you continue up or down away from the movieclip, you are still not able to go right anymore...
I've been baffled by this for a long time, so I thought it was about time I asked for help. I couldn't find anything on how to control movement in a top-down game, with a scrolling map + wall :/
The simplest (but not most resource friendly) solution (if you anyway have a single storage for walls) is iterating through the walls and instead of using the Flash default hitTest (I don't like the way it works since ActionScript 2) - just check the coordinates and if you see that there's going to be a collision on the next simulation step - handle it according to the game logic.
The most useful optimization for this algorithm is creating a filter/data structure for getting only walls that are near to the player and so can be affected to the test for collisions.