FlxG.collide (with setTileProperties) colliding outside the tile space in flixel - actionscript-3

so I have been using flixel I some recently, and I think I am getting a feel for it, but I have come across a issue.
I have a Map class, that uses the loadMap() function, which comes out great.
I then use setTileProperties() on my Water tile, that then calls a function, calls a Boolean on my player class (to say that he is in the water), which then slows him down. This still works great, except for one thing. When I pass the water tile above or to the right (about 10-16ish pixels, haven't gotten the exact number) outside the tile, it still slows the player. I am not sure if this is just the way that FlxG.collide() works, or if there is something I can do to fix it, or maybe if I should find another way to use the collision. All help is appreciated.
Here is the code, if you need it:
Map.as
private function createMap():void {
loadMap(new currentMap, currentTiles, 32, 32, 0, 0, 0);
setTileProperties(4, FlxObject.NONE, PlayerInWater);
}
override public function update():void {
super.update();
FlxG.collide(Registry.player, this);
}
private function PlayerInWater(tile:FlxTile, player:Player):void {
Registry.player.inWater = true;
trace("player is in the water");
}

So, I have figured out an answer to this, for all of you who want to know.
I used the overlapsPoint() method to create this:
private function createMap():void {
//load Map
loadMap(new currentMap, currentTiles, 32, 32, 0, 0, 0);
//set water tiles
setTileProperties(4, FlxObject.NONE);
//put all of the water tiles in an array
waterArray = getTileCoords(4);
}
override public function update():void {
super.update();
//collision with map
FlxG.collide(Registry.player, this);
//loops through each water tile
for each(var waterTile:FlxPoint in waterArray) {
//checks if the player is overlapping the water tile
if (Registry.player.overlapsPoint(waterTile)) {
//if so, then the player is in water
Registry.player.inWater = true;
}
}
}
This method being so simple, it kind of makes me feel stupid for getting stuck on it, but if someone finds a more efficient method, please, go ahead and comment, or make a new answer. I always appreciate feedback.

Related

AS3 tween object not working with .hitTestObject()

I am having a major problem in my new browser app.
Okay so I made game where different cubes (squares) spawn at the top of the screen and I use the Tween class to make them go down the screen and then disappear.
However I want to detect a collision when a cube hits the player (that is also a flying cube).
I tried everything, truly everything but it does not seem to work. The problematic thing is that when I remove the "Tween" function it does detect collision with the hitTestObject method but when I add the "Tween" line collision won't be detected anymore.
It looks like this:
function enemiesTimer (e:TimerEvent):void
{
newEnemy = new Enemy1();
layer2.addChild(newEnemy);
newEnemy.x = Math.random() * 700;
newEnemy.y = 10;
if (enemiesThere == 0)
{
enemiesThere = true;
player.addEventListener(Event.ENTER_FRAME, collisionDetection)
}
var Tween1:Tween = new Tween(newEnemy, "y", null, newEnemy.y, newEnemy.y+distance, movingTime, true);
}
And the collision detection part:
private function collisionDetection (e:Event):void
{
if (player.hitTestObject(newEnemy))
{
trace("aaa");
}
}
I am desperate for some information/help on the topic, it's been bugging me for days.
Thanks for your time, I would be very happy if someone could help me out^^
First, make sure the "newEnemy" instance and the "player" instance are within the same container. If they are not, their coordinate systems might not match up and could be the source of your problem.
Otherwise, you need to keep a reference to each enemy instance you create. It looks like you are only checking against a single "newEnemy" variable which is being overwritten every time you create a new enemy. This might be why you can successfully detect collision between the player and the most recent "enemy" instance.
So... you need a list of the enemies, you can use an Array for that.
private var enemyList:Array = [];
Every time you create an enemy, push it to the Array.
enemyList.push(newEnemy);
In your "collisionDetection" function, you need to loop through all of the enemies and check if the player is touching any of them.
for(var i:int = 0; i < enemyList.length; i++)
{
var enemy = enemies[i];
if (player.hitTestObject(enemy))
{
trace("Collision Detected!");
enemy.parent.removeChild(enemy); // remove the enemy from the stage
enemies.splice(i, 1); // remove the enemy from the list
}
}
I'd suggest that you move to TweenMax, it just might solve your problem, and in my experience it's much better in every possible way.
Scroll down the following page to see a few variations of this library, I myself use TweenNano, they're completely free of charge:
https://greensock.com/gsap-as
I think some plugins cost money, but I doubt you'll ever need them.

Collision doesn't work work if i drag too fast

I'm searching for this all day but it gives me the answer-box2d and I'm just a BEGINNER, box2d is advance for me, i don't really understand it. Someone help me, any answer will be appreciated.
hero.addEventListener(TouchEvent.TOUCH_BEGIN, touchhero);
stage.addEventListener(TouchEvent.TOUCH_END, drophero);
var dragbound1:Rectangle = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
function touchhero(event:TouchEvent):void
{
hero.startTouchDrag(event.touchPointID, false, dragbound1);
stage.addEventListener(Event.ENTER_FRAME, gohero);
}
function drophero(event:TouchEvent):void
{
hero.stopTouchDrag(event.touchPointID);
}
function gohero(event:Event):void{
if(hero.hitTestObject(wall)){
//popup something
}
}
You should use pixel perfect collision detection. Firstly you still want to check if your MovieClip's bounding box collides with another (the same method you're currently using). This is done to save your game from constantly checking the collision in such detail. If this is the case you can now check for the pixel collision.
Here's a good tutorial on this: http://code.tutsplus.com/tutorials/pixel-level-collision-detection--active-10862

universal collision detection for action script 3

I'm writing a game where you have to go through a maze. I want this game to have different levels. But for each level, the maze is going to be different. So I drew other walls. But I do not want to write my collision detection method 50 times if I have 50 different levels.
I thought of a way of fixing it, but it's not working. I created a new symbol with nothing in it and named it wall. I think that I can make my wall = wall1 (another symbol I converted, and exported for as), and just do stage.addChild(wall). But I can't find a way to do that. So I need help!
Make a generic class e.g. Wall and make your library symbols use that for their base class. You won't need to create them at runtime using ActionScript for this inheritance to work, you can still just place your MovieClips on the stage.
The next thing you need to do is store these Walls somewhere. Because you seem inexperienced with ActionScript, and want to avoid writing code for new levels, you can automate this process using a manager type class. We will call this class WallManager and it will look like this:
public class WallManager
{
private static var _walls:Vector.<Wall> = new <Wall>[];
internal static function register(wall:Wall):void
{
_walls.push(wall);
}
public static function reset():void
{
_walls = new <Wall>[];
}
public static function get walls():Vector.<Wall>{ return _walls; }
}
Then we'll create your Wall class. Within the constructor for this class, we will automatically have the Wall add itself into the WallManager listing:
public class Wall extends Sprite
{
public function Wall()
{
WallManager.register(this);
}
public function touchingMouse(mouseX:int, mouseY:int):Boolean
{
// For this example I am checking for collisions with the
// mouse pointer. Replace this function with your own collision
// logic for whatever it is that is supposed to collide with
// these walls.
if(parent === null) return false;
var bounds:Rectangle = getBounds(parent);
return bounds.contains(mouseX, mouseY);
}
}
This setup is not 'best practice', but it is suitable in your situation because your project seems small, you appear to be working on it alone, it's simple and it gets the job done.
At the end of each level, use WallManager.reset() to remove the walls from the previous level. For checking collisions across all walls, just use a loop like this:
for each(var i:Wall in WallManager.walls)
{
var collision:Boolean = i.touchingMouse(mouseX, mouseY);
if(collision)
{
// There was a collision.
//
//
}
}
You can make one MovieClip with 50 frames saying stop() on the first frame and do your code like this:
private var wallnum:int;
public function Main()
{
stop();
wallnum = 1;
var wallobj = new Wall();
addChild(wallobj);
wallobj.gotoAndStop(wallnum);
}
For collision detection, I recommend Pixel Perfect Collision Detection (https://code.google.com/p/master-air-controller/source/browse/trunk/master-air-controller/src/PixelPerfectCollisionDetection.as?spec=svn6&r=6)

AS3 layer order

I created two empty Sprites to serve as layers, bottom_spr and top_spr
When clicking a button, a MovieClip appears and follows your mouse, untill you click, then its position is fixed.
As soon as the button is clicked, I addChild the MovieClip to the correct Sprite.
Unfortunately, the layer system doesn't see to work, because they are layered in the order I place them, the Sprites don't seem to influence it.
How is this possible?
private var ground_spr:Sprite;
private var units_spr:Sprite;
public function Game() {
addEventListeners();
ground_spr = new Sprite();
units_spr= new Sprite();
addChild(ground_spr);
addChild(units_spr);
}
private function addEventListeners(){
groundBtn.addEventListener(MouseEvent.CLICK, clickGroundBtn);
unitBtn.addEventListener(MouseEvent.CLICK, clickUnitBtn);
}
private function clickGroundBtn(event:MouseEvent){
var ground = new Ground_mc();
follow();
ground_spr.addChild(ground);
}
private function clickUnitBtn(event:MouseEvent){
var unit = new Unit_mc();
follow();
units_spr.addChild(unit);
}
Your question is very vague but I will attempt to answer it. If you clarify how you want your objects ordered exactly, I can better answer your question. It is fine to add layer of abstraction over the depth handling, if you need it. In this case I dont see much of a need, but I will show you a few things you could do.
To add an object to the back of the screen:
this.setChildIndex(objName, 0);
To add an object to the front of the screen:
this.setChildIndex(objName, this.numChildren - 1);
To swap the depths of two objects:
this.swapChildren(objA, objB);
//Note this is expecting two DisplayObjects so you may have to do:
this.swapChildren(objA as DisplayObject, objB as DisplayObject);

Is it okay to put game logic in a draw function?

I am making a game, and I have finally finished the gameplay aspect of it, but now it's time for me to create a menu and a high scores screen. I'm not entirely sure how to do it, the game will be in a different state (MENU_STATE, GAMEPLAY_STATE, SCORESCREEN_STATE) and in each state I want to draw different things to the screen, is it okay for me to do something like this then?
draw function()
{
if MENU_STATE
draw menu
if GAMEPLAY_STATE
draw game
if SCORESCREEN_STATE
draw scores
}
I've been following a strictly no logic in the draw function and it's been good so far, but I really can't figure out a different way to do this.
You could use separate classes for the three states, implementing a common interface, and rather than setting a constant for state, set an instance of one of the classes:
interface IState {
void draw();
}
class Menu implements IState {
void draw() {
// Draw menu
}
}
class Game implements IState {
void draw() {
// Draw game
}
}
void draw() {
state.draw();
}
This still isn't ideal (you don't really want drawing code in your state, you want something a bit more separate), but the abstraction is a common one and could be relevant (and it's hard to advise further without knowing more of your architecture).
You are calling some drawing functions in that routine but that doesn't mean
you have to name it draw.
Perhaps this is more appropriate in your case:
// pseudocode
on_game_state function(state)
{
select (state):
MENU_STATE:
draw menu
GAMEPLAY_STATE:
draw game
SCORESCREEN_STATE:
draw scores
}
Using a statemachine would make this simpler. Each state will have its own set of update and draw functions that are called when it is on top of the state stack. Instead of having one draw function with internal state switches you would have Game_Draw(), Menu_Draw(), HighScoreScreen_Draw() etc. Similarly your update functions could be separated out.
static void StateMachine_DrawTopState()
{
switch(stateMachine_topState)
{
case STATE_GAMEPLAY:
{
Gameplay_Draw();
}
break;
case STATE_MENU:
{
Menu_Draw();
}
break;
}
}
Similar to Andrew Aylett's answer and assuming an object-oriented language, perhaps you could do something like:
Interface IState {
void init();
void update();
void draw();
}
class GameplayScene implements IState {
void init() {
// initialize gameplay
}
void update() {
// update game logic
}
void draw() {
// draw game
}
}
class MenuScene implements IState {
void init() {
// initialize menu
}
void update() {
// update menu logic
}
void draw() {
// draw menu
}
}
class ScoresScene etc...
class TitleScene etc...
// Somewhere else, probably in the Game class
void Main() {
// Init game
Scene currentScene = new TitleScene;
while (Scene != null) {
Scene.init();
Scene.update();
Scene.draw();
}
// Exit game
}
You would also need to think about how to handle transition between scenes. You could have each scene class have a member variable called something like nextScene and the main function queries it at the start of the loop to switch to the proper scene.
If you don't have the luxury of using an object-oriented programming language (like C++, Java, C#, Python, etc.), both Colin's and Nick D's answers might help, although I'd try to have the switch statement in one place (say one big game_update function) to allow adding new states by making a change in one place. Alternatively, you could build on the Colin's state machine design to make something more generic and that doesn't explicitly require a hard-coded switch statement. (although to be honest I can't think of a good way to do it at the moment)
It is absolutely not ok to put game logic in a draw function.
However, if it makes your life easier in this specific case, it's ok anyway.
You can always change it later if it becomes a mess.
Yes it's fine, game programmers are allowed to bend the rules for performance gains. The view and the model of a game world are quite often one and the same thing to avoid latency created by decoupling the view and the model.
There's no reason why you can't make the menu and highscores objects part of your game world, it's been done before in quite a few games.