ActionScript3: how to initialize array length in object after it has been declared? - actionscript

I'm using an AS3 class that is:
package {
public class PeopleInfo {
public var elements:int;
public var PeopleName:Array;
public var PeopleInt:Array;
public var PeopleDecimal:Array;
}
}
In another file I've got:
<?xml version="1.0" encoding="utf-8"?>
<s:Application
creationComplete="initApp()"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
public var ii:int;
public var dataWriteToDB:PeopleInfo = new PeopleInfo;
public function initApp():void
{
// Initialize data provider array.
var int_data:Array = new Array(10, 20, 30, 40, 50);
var decimal_data:Array = new Array(13.11, 23.34, 35.69, 43.29, 58.92);
var name:Array = new Array("Joe", "Karen", "Simon", "Greg", "Alice");
dataWriteToDB.elements = 5; // number of elements in array
for (ii = 0; ii < dataWriteToDB.elements; ii++)
{
dataWriteToDB.PeopleName[ii] = name[ii];
dataWriteToDB.PeopleInt[ii] = int_data[ii];
dataWriteToDB.PeopleDecimal[ii] = decimal_data[ii];
}
}
and so on...
I'm getting a run-time error: Error #1009: Cannot access a property of method of a null object reference referring to the for loop's first line dataWriteToDB.PeopleName since it is NULL.
I'm guessing the problem here is that while dataWriteToDB is declared initially, the array lengths for the arrays in PeopleInfo class have not been set yet. Or, not sure otherwise why it's NULL. Anyone know how to clear this up?

The arrays have not been initialized in the class. You should do it in the declaration:
package {
public class PeopleInfo {
public var elements:int;
public var PeopleName:Array = [];
public var PeopleInt:Array = [];
public var PeopleDecimal:Array = [];
}
}
Also consider using push to add elements to the array, to avoid accidentally accessing a non-existing index:
for (ii = 0; ii < dataWriteToDB.elements; ii++)
{
dataWriteToDB.PeopleName.push(name[ii]);
dataWriteToDB.PeopleInt.push(int_data[ii]);
dataWriteToDB.PeopleDecimal.push(decimal_data[ii]);
}

Related

Vala closure reference cycle

I'm writing a class in Vala where I bind two of the same object's properties together, with a closure to transform one to the other.
class Foo : Object
{
public int num { get; set; }
public int scale = 2;
public int result { get; set; }
construct {
this.bind_property("num", this, "result", 0,
(binding, src, ref dst) => {
var a = src.get_int();
var b = this.scale;
var c = a * b;
dst.set_int(c);
}
);
}
}
The closure keeps a reference this (because I use this.scale), which creates a reference cycle which is keeping my class alive even when all other references to it are lost.
The binding will only be removed when the reference count reaches 0, but refcount will only reach 0 when the biding and its closure is removed.
Is there a way to make the closure's reference to this weak? Or to probe when the refcount reaches 1 in order to remove it?
Not tested but can you assign this to a weak variable and reference that in the closure instead? E.g.:
weak Foo weak_this = this;
this.bind_property(…, (…) => {
…
b = weak_this.scale;
…
}
This is a known defficiency of the Vala compiler and is discussed in this issue.
For now, the problem can be avoided by doing the binding from a static method where the closure does not capture this.
class Foo : Object
{
public int num { get; set; }
public int scale = 2;
public int result { get; set; }
construct {
this.bind_properties(this);
}
private static void bind_properties(Foo this_)
{
weak Foo weak_this = this_;
this_.bind_property("num", this_, "result", 0,
(binding, src, ref dst) => {
var a = src.get_int();
var b = weak_this.scale;
var c = a * b;
dst.set_int(c);
}
);
}
}

keeping track of a series of simple multiple choice web form answers

This is the code I'm trying to use, which seems logical. But doesn't seem to be working.
MyAsFileName.prototype.getTotalScore = function() {
var totalScore = 0;
for (var i = 0; i < allQuestions.length; i++) {
totalScore += allQuestions[i].getCalculatedScore();
if (currentModule.allQuestions[i].parent.questionCorrect == true) {
knowledgePoints++;
} else {
knowledgePoints--;
}
}
debugLog("Total score: " + totalScore);
debugLog(knowledgePoints);
return totalScore;
}
I have allQuestions defined as below:
var allQuestions = Array();
I have knowledgePoints defined as:
this.knowledgePoints = 10;
I have questionCorrect defined as:
this.questionCorrect = false;
Second fresh attempt made with new class as answer below suggested (commented out for now until I figure out how to get working):
// package
// {
/*public class Quiz {
//public
var knowledgePoints: int = 10;
//public
var allQuestions: Array = new Array;
//public
var questionCorrect: Boolean = false;
//public
function getTotalScore(): int {
var totalScore: int = 0;
for (var i = 0; i < allQuestions.length; i++) {
totalScore += allQuestions[i].getCalculatedScore();
if (currentModule.allQuestions[i].parent.questionCorrect) {
knowledgePoints++;
} else {
knowledgePoints--;
}
}
debugLog("Total score: " + totalScore);
debugLog(knowledgePoints);
return totalScore;
}
}*/
//}
This code above outputs two errors in flash console:
Error 1. Attribute used outside of class.
Error 2. 'Int' could not be loaded.
It's a weird (and actually non-AS3 way) way to do this. Instead of creating a unnamed closure which refers weird variables from who-knows where, you should make it a normal AS3 class, something like that (in a file named Quiz.as):
package
{
public class Quiz
{
public var knowledgePoints:int = 10;
public var allQuestions:Array = new Array;
public var questionCorrect:Boolean = false;
public function getTotalScore():int
{
var totalScore:int = 0;
// Your code does not explain how you will that Array.
// It is initially an empty Array of length 0.
for (var i = 0; i < allQuestions.length; i++)
{
totalScore += allQuestions[i].getCalculatedScore();
if (currentModule.allQuestions[i].parent.questionCorrect)
{
knowledgePoints++;
}
else
{
knowledgePoints--;
}
}
// Not sure what it is.
debugLog("Total score: " + totalScore);
debugLog(knowledgePoints);
return totalScore;
}
}
}

1067: Implicit Coercion of a value

So I'm currently trying to run my collision test on my two sprites, and I'm getting the following error:
C:\\Code\\Game\Game.as, Line 54, Column 34 1067: Implicit coercion of a value of type mvc:PlayerModel to an unrelated type assets.Scripts:SpriteAnimation.
Which is pointing to the following line of code:
handleSpriteToSpriteCollision(_player, _boss);
The function is as follows:
private function handleSpriteToSpriteCollision(sprite1:SpriteAnimation, sprite2:SpriteAnimation):void
{
var toSprite2 : VectorModel = new
VectorModel(0,0,0,0, sprite2.x - sprite1.x, sprite2.y - sprite1.y);
var bitmapData1:BitmapData = new BitmapData(sprite1.width, sprite1.height);
while(testBitmapCollision(sprite1.spriteFrameBitmapData, sprite1.topLeftX, sprite1.topLeftY, sprite2.spriteFrameBitmapData, sprite2.topLeftX, sprite2.topLeftY))
{
sprite2.x -= toSprite2.dx;
sprite2.y -= toSprite2.dy;
}
}
Both sprites display just fine, but as soon as I make the function call it all comes crumbling down. At this point I just need some fresh eyes to take a look at the code to see what's going wrong.
Edit: Here is the PlayerModel.as
package mvc
{
import flash.events.Event;
import flash.events.EventDispatcher;
import assets.Scripts.SpriteAnimation;
public class PlayerModel extends EventDispatcher
{
private var _previousX:Number = 0;
private var _previousY:Number = 0;
private var _xPos:Number = 0;
private var _yPos:Number = 0;
public var vx:Number = 0;
public var vy:Number = 0;
private var _height:uint = 30;
private var _width:uint;
private var _color:uint;
public function PlayerModel():void
{
}
public function update():void
{
xPos += vx;
yPos += vy;
}
public function get height():uint
{
return _height;
}
public function get color():uint
{
return _color;
}
public function get xPos():Number
{
return _xPos;
}
public function set xPos(value:Number):void
{
_xPos = value;
dispatchEvent(new Event(Event.CHANGE));
}
public function get yPos():Number
{
return _yPos;
}
public function set yPos(value:Number):void
{
_yPos = value;
dispatchEvent(new Event(Event.CHANGE));
}
public function set setX(value:Number):void
{
_previousX = value - vx;
xPos = value;
}
public function set setY(value:Number):void
{
_previousY = value - vy;
yPos = value;
}
}
}
The first thing i would check is the class of your boss and player objects inherit your SpriteAnimation class:
class PlayerModel extends SpriteAnimation
{ ...
Seems as though your handleSpriteToSpriteCollision function is looking for two SpriteAnimations and at least the PlayerModel being passed isn't one
Sprite inherits EventDispatcher so as long as your SpriteAnimation inherits Sprite as well, you shouldn't lose any functionality

Adding a parameter to GetItems in DotNetNuke sample Module

Below is the code from the DotNetNuke Sample module that gets a collection of items from the database that belong to a particular module. What I want is add a second parameter for it filter by. I'm guessing this has something to do with modifying the scope item.cs class but am not sure how exactly.
public IEnumerable<Item> GetItems(int moduleId)
{
IEnumerable<Item> t;
using (IDataContext ctx = DataContext.Instance())
{
var rep = ctx.GetRepository<Item>();
t = rep.Get(moduleId);
}
return t;
}
Any ideas?
Another way to do it in DAL2 is using the .Find() method. This is good if you want to query on an indexed field in your table and you don't care about caching scope:
public IEnumerable<Item> GetItemByName(int moduleId, string itemname)
{
IEnumerable<Item> t;
using (IDataContext ctx = DataContext.Instance())
{
var rep = ctx.GetRepository<Item>();
t = rep.Find("WHERE ModuleId = #0 AND ItemName LIKE #1", moduleId, itemname);
}
return t;
}
Here's some sample code from my SignalRChat module that uses DAL2 (http://signalrchat.codeplex.com/SourceControl/changeset/view/71473#1272188)
public IEnumerable<Message> GetRecentMessages(int moduleId, int hoursBackInTime, int maxRecords)
{
var messages = (from a in this.GetMessages(moduleId) where a.MessageDate.Subtract(DateTime.UtcNow).TotalHours <= hoursBackInTime select a).Take(maxRecords).Reverse();
return messages.Any() ? messages : null;
}
That is one approach, you can also use a SQL statement within the controller as well (http://signalrchat.codeplex.com/SourceControl/changeset/view/71473#1272186)
public ConnectionRecord GetConnectionRecordByConnectionId(string connectionId)
{
ConnectionRecord t;
using (IDataContext ctx = DataContext.Instance())
{
var connections = ctx.ExecuteQuery<ConnectionRecord>(CommandType.Text,
string.Format(
"select top 1 * from {0}{1}SignalRChat_ConnectionRecords where ConnectionId = '{2}'",
_databaseOwner,
_objectQualifier,
connectionId)).ToList();
if (connections.Any())
{
t = connections[0];
}
else
return null;
}
return t;
}

how to remove an object with as2 on a frame #

i'm using as2. How do i delete these snowfalkes on a certain frame? i'm creating the snowlfakes using an array on frame 40. I want to get rid of the frames around 60.
var snowflake:Array;
for (var i:Number=0;i<100;i++) {
snowflake[i]=new Snowflake(this);
}
import Snowflake.*;
class Snowflake {
public var _snowflake:MovieClip;
private var _ranSnowflake:Number;
private var i:Number;
private var k:Number;
private var rad:Number;
private static var NUM_SNOWFLAKE_TYPES:Number=7;
private static var MOVIE_WIDTH:Number=590;
private static var MOVIE_HEIGHT:Number=390;
private static var FALLING_SPEED:Number=30;
private static var WIND_SPEED:Number=5;
private static var ROTATION_SPEED:Number=4;
function Snowflake(container:MovieClip) {
this._ranSnowflake=Math.round((Math.random()*Snowflake.NUM_SNOWFLAKE_TYPES)+1);
this._snowflake=container.attachMovie("snowflake"+this._ranSnowflake,"snowflake",container.getNextHighestDepth());
this._snowflake._x=(Math.random()*Snowflake.MOVIE_WIDTH);
this._snowflake._y=0;
this._snowflake.parent=this;
this.i=1+Math.random()*2;
this.k=-Math.PI+Math.random()*Math.PI;
this.rad=0;
//giving each snowflake unique characteristics
this._snowflake._xscale = this._snowflake._yscale=Math.random()*30;
this._snowflake._alpha = 75+Math.random()*100;
this._snowflake.onEnterFrame=function() {this.parent.snowflakeEnterFrame(this._snowflake);}
trace("SNOWFLAKE X:"+this._snowflake._x+" Y:"+this._snowflake._y);
trace(this._currentframe);
}
public function snowflakeEnterFrame() {
//putting it all together
this.rad += (k/180)*Math.PI;
this._snowflake._x -= Math.cos(rad);
this._snowflake._y += i;
if (this._snowflake._y>=Snowflake.MOVIE_HEIGHT) {
this._snowflake._y = -Snowflake.FALLING_SPEED;
}
if ((this._snowflake._x>=Snowflake.MOVIE_WIDTH) || (this._snowflake._x<=0)) {
this._snowflake._x = -Snowflake.WIND_SPEED+Math.random()*Snowflake.MOVIE_WIDTH;
this._snowflake._y = -Snowflake.WIND_SPEED;
}
this._snowflake._rotation+=Snowflake.ROTATION_SPEED;
}
public function vis(){
this._snowflake.visible = false;
}
}
Something like this (should work on any frame):
for(var i:Number = 0; i<snowflake.length; i++){
this.removeMovieClip(snowflake[i]._snowflake);
}
Loop through all the snowflake and remove them from the container.

Resources