List Component - Change gap size between cells - actionscript-3

I want to increase the gap size between cells in my list so they won't be on top of each other. I know there is m_list.setStyle("contentPadding", 5) but that only adjusts the gap from the edges of the list and not the individual cells. Also adjusting the rowHeight on the list does not effect the gap between adjacent cells. I can't seem to find any resources on how this is done.
Thanks in advance.

It's not support with api. You may create own List extends fl.controls.List and use trick with rowHeight, see down:
package
{
import fl.controls.List;
import fl.controls.listClasses.CellRenderer;
public class MyList extends List
{
public var gap:Number = 5;
public function MyList()
{
super();
rowHeight += gap;
}
override protected function draw():void
{
super.draw();
updateRenderer();
}
protected function updateRenderer():void
{
var renderers:Array = availableCellRenderers.concat(activeCellRenderers);
var l:uint = renderers.length;
for (var i:uint=0; i<l; i++)
{
var renderer:CellRenderer = renderers[i];
if (i > 0)
{
renderer.y += gap;
}
renderer.setSize(availableWidth+_maxHorizontalScrollPosition,rowHeight - gap);
renderer.drawNow();
}
}
}
}

Related

Removing an Object when it hits another object AS3

Beginner here. I have a symbol on the timeline with an instance name of 'island', so basically I want to remove the cells that hits the 'island'
if (cell.hitTestObject (island)) {
if(stage.contains(cell))
removeChild (cell);
}
I tried this one under the moveCell function but it only removes one cell instead of every cell that hits the island. Thanks everyone!
Here's my code so far:
package {
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Main extends MovieClip {
public var cell:Cell;
public var group:Array;
public var gameTimer:Timer;
public function Main() {
cell = new Cell (400, -15);
addChild (cell);
group = new Array();
var newCell = new Cell (100, -15);
group.push ( newCell);
addChild(newCell);
gameTimer = new Timer (25);
gameTimer.addEventListener(TimerEvent.TIMER,moveCell);
gameTimer.start();
}
public function moveCell (timerEvent:TimerEvent):void {
if (Math.random() < 0.01) {
var randomX:Number = Math.random() * 700;
var newCell:Cell = new Cell (randomX, -15);
group.push (newCell);
addChild(newCell);
}
for each(var i:MovieClip in group) {
if (i.hitTestObject(island)) {
i.visible = false;
//i.parent.removeChild(i);
var score:int = 0;
score ++;
scoreOutPut.text = score.toString();
}
}
}
}
}`
You got the "Cannot access a property or method of a null object reference" because you've removed the Cell object from the DisplayObjectContainer (its parent) but not from the group array, so in the next iteration of your for loop, that object didn't exist anymore and that error will be fired.
To avoid that you can do like this :
for(var i:int = 0; i < group.length; i++)
{
var cell:Cell = Cell(group[i]);
if (cell.hitTestObject(island))
{
cell.parent.removeChild(cell);
group.splice(i, 1);
score++;
}
}
For the score, it should be a global property for all your class to get updated every time.
Also, for your code to be more organised and clearer, it's better to put every task in a single method.
For example, for creating cells, you can use a createCell() method :
// 0 is the default value of __x and -15 is the default one of __y
private function createCell(__x:Number = 0, __y:Number = -15): void
{
var cell:Cell = new Cell(__x, __y);
group.push(cell);
addChild(cell);
}
Then you can use it in any place in your code, for example, for your two first cells that you create in the constructor :
public function Main()
{
// ..
createCell(400);
createCell(100);
// ...
}
Or inside the moveCell() method :
if (Math.random() < 0.01)
{
var randomX:Number = Math.random() * 700;
createCell(randomX);
}
Also, if you don't really need that a property or a method to be public, don't put it as public.
...
Hope that can help.

How can I hide the TabNavigator gap in Flex 4.6?

I tried extending TabNavigator and overriding contentY, but it references private tabBarHeight, so to get around that I simply copied the getter contents into my override and subtracted the unwanted 12 pixels, but that made absolutely zero difference.
Anyone have any ideas (Aside from switching to a viewstack!)?
public class Tabber extends TabNavigator
{
public function Tabber(){
super();
}
override protected function get contentY():Number {
var paddingTop:Number = getStyle("paddingTop");
if (isNaN(paddingTop))
paddingTop = 0;
var tabHeight:Number = getStyle("tabHeight");
if (isNaN(tabHeight))
tabHeight = tabBar.getExplicitOrMeasuredHeight();
var tabBarHeight:Number = tabHeight - borderMetrics.top;
return tabBarHeight + paddingTop - 12;
}
}
Have you tried setting tabHeight (with setStyle method)?
Because TabNavigator uses it:
private function get tabBarHeight():Number
{
var tabHeight:Number = getStyle("tabHeight");
if (isNaN(tabHeight))
tabHeight = tabBar.getExplicitOrMeasuredHeight();
return tabHeight - borderMetrics.top;
}
Or maybe changing the verticalGap style...

as3 dynamic Names for StageText / NativeText

does anyone know how to dynamically assign a name to NativeText / StageText as i am trying to build a dynamic interface instead of hardcoding it in, any help would be appreciated!
You should keep references to the dynamically created instances of StageText as you cannot get it by querying the display list (as it is not on display list). You can have the vector of of StageText
var m_vStageTextInstances:Vector<StageText>;
Then after you will just iterate over this vector.
Here's some example code that does what you want inside the iterate-function
public class IterationTest extends Sprite {
public function IterationTest() {
createObjects();
iterate();
}
private function createObjects():void {
for (var i:int = 0; i < 1000; i++) {
addChild(new TextField());
addChild(new MovieClip());
}
}
private function iterate():void {
var numTextObjects:int = 0;
for (var i:int = 0; i < this.numChildren; i++) {
var child:DisplayObject = getChildAt(i);
if (child is TextField) {
//do your stuff here
}
}
}
}
if anyone is trying to return text values with NativeText a StageText wrapper. they will need to edit;
https://github.com/cantrell/StageTextExample/blob/master/src/NativeText.as
add a public get function -
public function get text():String {
return this.st.text;
}
then you can return the NativeText values normally -
nt.text

How to make new bubbles stack in my Bubble Shooter game?

I'm making a Bubble Shooter game, and I'm trying to make the bubble I'm fireing to stack and then be at the right place in the column. The bubbles I've placed on the board looks like this:
000000000000000
000000000000000
000000000000000
000000000000000
There's 4 rows with 15 bubbles. This is the code I have written so far:
Main
package {
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.display.SpreadMethod;
public class Main extends Sprite {
private const ROT_SPEED:uint=2;
private const R:uint=18;
private const DEG_TO_RAD:Number=0.0174532925;
private const BUBBLE_SPEED:uint=10;
private var bubbleArr:Array=new Array();
private var loadArr:Array=new Array();
private var cannon:cannon_mc;
private var bubble:bubble_mc;
private var row:uint=0;
private var col:uint=0;
private var left:Boolean=false;
private var right:Boolean=false;
public var bubCont:Sprite;
private var loadCont:Sprite;
private var fire:Boolean=false;
private var vx,vy:Number;
public function Main() {
placeContainer();
placeCannon();
loadBubble();
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKDown);
stage.addEventListener(KeyboardEvent.KEY_UP,onKUp);
addEventListener(Event.ENTER_FRAME,onEFrame);
trace("row= "+row+" , col= "+col);
}
private function placeCannon():void {
cannon=new cannon_mc();
addChild(cannon);
cannon.y=385.5;
cannon.x=320;
}
private function onKDown(e:KeyboardEvent):void {
switch(e.keyCode) {
case 37 :
left=true;
break;
case 39 :
right=true;
break;
case 38 :
if (! fire) {
fire=true;
var radians=(cannon.rotation-90)*DEG_TO_RAD;
vx=BUBBLE_SPEED*Math.cos(radians);
vy=BUBBLE_SPEED*Math.sin(radians);
}
break;
}
}
private function onKUp(e:KeyboardEvent):void {
switch(e.keyCode) {
case 37 :
left=false;
break;
case 39 :
right=false;
break;
}
}
private function onEFrame(e:Event):void {
if (left) {
cannon.rotation-=ROT_SPEED;
}
if (right) {
cannon.rotation+=ROT_SPEED;
}
if (fire) {
bubble.x+=vx;
bubble.y+=vy;
if (bubble.x<59) {
bubble.x=59;
vx*=-1;
}
if (bubble.x>(59+R*R)) {
bubble.x=59+R*R;
vx*=-1;
}
if (bubble.y<(40)) {
bubble.y=40;
}
}
}
public function placeContainer():void {
var iRow:Boolean=false;
bubCont=new Sprite();
addChild(bubCont);
for (var i:uint=0; i<4; i++) {
if (! iRow) {
for (var j:uint=0; j<15; j++) {
bubbleArr[i]=new Array();
bubbleArr[i][j]=Math.floor(Math.random()*6);
bubble = new bubble_mc(bubbleArr[i][j],i,j);
bubCont.addChild(bubble);
iRow=true;
row++;
col++;
}
} else {
for (j=0; j<15; j++) {
bubbleArr[i]=new Array();
bubbleArr[i][j]=Math.floor(Math.random()*6);
bubble = new bubble_mc(bubbleArr[i][j],i,j);
bubble.x=77+j*2*R;
bubCont.addChild(bubble);
iRow=false;
row++;
col++;
}
}
}
}
private function loadBubble():void {
addChild(bubble);
bubble.gotoAndStop(Math.floor(Math.random()*6))+1;
bubble.x=320;
bubble.y=410;
}
}
bubble_mc class:
package {
import flash.display.MovieClip;
public class bubble_mc extends MovieClip {
public function bubble_mc(val:uint,row:uint,col:uint) {
gotoAndStop(val+1);
name=row+"_"+col;
x=59+col*36;
y=40+row*32;
}
}
I have absolutley no idea how to make the bubbles stack together.. I have tried using hitTestObject-function and I have tried to write my own function that checks for collision and then calls a function that is supposed to place the bubble in the right place, but it doesn't work and I dont know why. I'm getting a error called TypeError: Error #1010.
Here is the collision function and the parkBubble function- which is supposed to place the bubbles in the right place:
private function parkBubble(bubble:bubble_mc,row:int,col:int):void {
var iRow:Boolean=false;
for (var j:uint=0; j<col; j++) {
trace("first for loop ");
for (var i:uint=row; i>0; i--) {
trace("second for loop ");
if (bubbleArr[i][j]!=null) {
trace("first if loop ");
if (! iRow) {
trace("second if loop ");
bubbleArr[i+1]=new Array();
bubbleArr[i+1][j]=Math.floor(Math.random()*6);
bubble = new bubble_mc(bubbleArr[i+1][j],(i+1),j);
bubCont.addChild(bubble);
iRow=true;
row++;
col++;
} else {
trace("first for loop after else ");
bubbleArr[i+1]=new Array();
bubbleArr[i+1][j]=Math.floor(Math.random()*6);
bubble = new bubble_mc(bubbleArr[i+1][j],(i+1),j);
bubble.x=77+j*2*R;
bubCont.addChild(bubble);
iRow=false;
row++;
col++;
}
}
}
}
removeChild(bubble);
fire=false;
loadBubble();
trace("slutet av parkBubble ");
}
private function collide(bub:bubble_mc):Boolean {
var dist_x:Number=bub.x-bubble.x;
var dist_y:Number=bub.y-bubble.y;
return Math.sqrt(dist_x*dist_x+dist_y*dist_y)<=2*R-4;
}
Was the TypeError on this line?
var placed_bubble:bubble_mc=new bubble_mc([row][col],row,col);
The [row] is an array, and [col] is an array. But the constructor expects an unsigned integer:
public function bubble_mc(val:uint,row:uint,col:uint) {
In order to copy the bubble to the bubble container, pass the frame number:
var placed_bubble:bubble_mc=new bubble_mc(bubble.currentFrame-1, row, col);
This might not be the only problem. TypeError often results from a variable not being defined, which could be from some other code that modifies the variable "bubble". For example, placeContainer assigns the bubbles in the container to the variable "bubble".
The function parkBubble always sets "iRow" to false, but if the bubble collides with a row above it that is odd you want iRow to be true.
var row:uint=Math.floor(bubble.y/(40+R*Math.sqrt(3)));
var iRow:Boolean= row % 2 == 1 ? true : false;
After it is at least compiling, you'll have less problems if you go back and simplify and optimize the math with some constant names. Then you'll more easily see the above code for calculating the row is not quite right. It should subtract the top margin (40). That is obvious with named constants:
private const Y_PER_ROW:int = int(R * Math.sqrt(3));
private const TOP:int = 40;
...
var row:uint = int((bubble.y - TOP) / Y_PER_ROW);
I would double-check your other calculations, too. Puzzle Bobble games usually set the odd rows to horizontally offset at radius, not at 2 radius (2 * R). So they fit together like hexagons.
The placeContainer function could be simplified. Most of the code in even or odd rows is the same, so could be taken out of the if block. And in this code you posted, I don't see why you need "row++" and "col++" in placeContainer. This is equivalent and easier to read:
for (var i:uint=0; i<4; i++) {
var xOffset:int = (i % 2) * 2 * R;
for (var j:uint=0; j<15; j++) {
bubbleArr[i] = new Array();
bubbleArr[i][j] = int(Math.random()*6);
bubble = new bubble_mc(bubbleArr[i][j], i, j);
bubble.x += xOffset;
bubCont.addChild(bubble);
row++;
col++;
}
}
Then, the collision detection code could be simplified and optimized to avoid calculations when the bubble is far away and avoid the expensive square-root calculation:
Circle Collision Detection HTML5 Canvas
http://cgp.wikidot.com/circle-to-circle-collision-detection

AS3 hitTestPoint always returns false for one function

I have a movieclip I drawn, called Map. It has a child with the name Wall. I'm trying to make a function that returns a 2d tile array of if there is something in that tile or not, for pathfinding.
The problem is, levelGrid is entirely false. I'm not sure what I am doing wrong.
I have filled the whole movieclip (Wall) with bright red, and yes it still returns false.
The x and y of both Map and Wall is 0, so I don't think there should be issues with hitTestPoint accepting global x / y.
They are added to a display list.
My other movement hittest works fine.
My code:
public function levelMap() {
for (var i = 0; i < height / 25; i++) {
levelGrid[i] = [];
for (var j = 0; j < width / 25; j++) {
levelGrid[i][j] = this.getChildByName("Wall").hitTestPoint(j*25,i*25,true);
}
}
trace(levelGrid);
}
Thanks in advance (levelGrid is a class variable)
I made a visual test out of your code. I did not change any functionality though so I think your problem is your graphics. Check the width, height och positions of the graphics. If you dont get anything in the Array, then maybe those values are not set correctly.
Each dot represent a hitTestPoint in this test. If its green you have a hit (true return value). Red means no hit. Hope this helps.
TestHitPoint.as
package
{
import flash.display.Sprite;
public class TestHitPoint extends Sprite
{
private static const TILE_SIZE : int = 25;
private var levelGrid : Array;
public function TestHitPoint()
{
// add graphics to test
addChild( new WallGraphics() );
// fix array
levelGrid = new Array();
// loop
for (var i : int = 0; i < height / TILE_SIZE; i++)
{
levelGrid[i] = [];
for (var j : int = 0; j < width / TILE_SIZE; j++)
{
var success : Boolean = this.getChildByName("Wall").hitTestPoint(j*TILE_SIZE, i*TILE_SIZE, true);
levelGrid[i][j] = success;
addChild( new PositionMarker(j*TILE_SIZE, i*TILE_SIZE, success) );
}
}
}
public function levelMap() : void
{
}
}
}
import flash.display.Sprite;
internal class WallGraphics extends Sprite
{
public function WallGraphics()
{
name = "Wall";
with(graphics)
{
beginFill(0x0000FF, 1);
drawRect(100, 50, 60, 200);
drawRect(50, 100, 200, 50);
endFill();
}
}
}
internal class PositionMarker extends Sprite
{
public function PositionMarker(posX : Number, posY : Number, success : Boolean)
{
with(graphics)
{
beginFill((success) ? 0x00FF00 : 0xFF0000, 1);
drawCircle(posX, posY, 4);
endFill();
}
}
}
Output: