Posted: 16th Oct 2011 6:08
Using arrays to manage players, enemies, bullets, etc. is a practice that should have died about 10 years ago. Where is the FOR.. EACH, DELETE and ADD/PUSH commands?

GLBasic has them, why doesn't AppGameKit?
Posted: 18th Oct 2011 2:14
AGK T1 (BASIC) is a great language for learning the core lessons of programming and rapid development but for those coders looking for modern techniques you best choice is T2 (C++) which offers everything from class structures to pointers. Rather than try to squeeze lots of advanced approaches into BASIC, or dumbing down C++, we decided to offer two flavours, to give each group the best chance based on what they are after.

We could still add dynamic data structures to the AppGameKit compiler, but we need to sit down and really plot out the best way to do it that compliments the existing AppGameKit command set. The danger is that by dropping in lots of alternative approaches to the problem of data management, we have a language that takes longer to learn and master. I often ask the question, what is it that you actually want to achieve which the current system cannot handle. It's a great starting point when discussing new additions to the language.
Posted: 18th Oct 2011 16:38
While GLBasic may have it, it's missing several things that AppGameKit has going for it. Particles, Box2D, Easier Sprite Manipulation etc...
Granted I would like to see a FOR/EACH, DELETE, ADD/PUSH added to AppGameKit as well, but given that it's a newer language may take a little bit for it to get implemented.
As Lee stated, adding too many commands can confuse people. Better to keep it simple at the moment.
Posted: 18th Oct 2011 23:32
As for language simplicity, I believe using For/Each to manipulate lists of objects instead of static arrays is way easier to learn, so if the idea is make the tier 1 Basic easy to learn, these would be nice additions to accomplish that.

For old school developer like me, who actually learn Basic as first language back in 1832, using static arrays are very natural, but some adding some modern commands would help a lot make the logic simpler.

Cheers
Posted: 19th Oct 2011 9:05
You make some excellent points Lee and I understand your concerns. I'd like to offer my two cents worth on the subject.

I don't think you have to make the rather large leap from Basic to C++ just to get the benefit of something like dynamic types. I feel dynamic types have become a modern Basic concept that is included in several other Basic-based languages similar to AGK. I agree that you don't want to move fully into some kind of Basic/C++ extreme hybrid (which others have done) but simplifying the management of players/enemies/bullets/etc in any game development environment should be a priority and I think it is very implementable within Tier-1. As far as Tier-1 being a beginner's language, well I can't think of many 2D games in the appstore that could not be written using Tier-1.

For example, I would prefer to manage my types this way:

ForEach bullet in bullet
ForEach ship in ships
if GetSpriteCollision( bullet.id, ship.id)
PlaySound(ship.sound)
Inc Score, ship.value
Delete ship
Delete bullet
endif
Next
Next

For one thing, this is faster than having to run through the entire length of both fixed arrays because there COULD be data in there. Another situation is when you spawn an enemy or a bullet, you don't have to run through the array to locate the first empty record in the array to create your new object. Also, being able to simply delete the type when you are finished with it is pretty darn awesome. I can't tell from the help file how you clear the data from an array record now without writing a null value to all the typed objects.

Simply stated, I think as is, handling enemies, ships, bullets, etc is more cumbersome than it needs to be. In my opinion, this is pretty easy stuff to learn and makes managing your objects a breeze. For people that don't want to learn to use these or don't like them then they have the options of sticking with arrays. I intended to switch over to AppGameKit for GLB but I suppose I am spoiled and it's tough for me to "set my watch back" to old school arrays.

Thanks.
Posted: 19th Oct 2011 10:51
It's perfectly possible to create a linked list inside a static array. The only problem is that it needs to be dimensioned to some adequate length before using it.
Posted: 23rd Oct 2011 3:50
@Alien Menace : You make a good case for FOR EACH. Post exactly how it would look in AppGameKit and we can work from there. Take the example of a bullet being fired, managed and destroyed as that often deals with a very dynamic list of objects during the game.
Posted: 25th Oct 2011 22:28
Here ya go..

+ Code Snippet
SetVirtualResolution ( 800, 600 )

// DIM THESE PARTICULAR TYPES AS DYNAMIC
Dim BulletType as Dynamic
Dim EnemyType as Dynamic

Global playerx
Global playery
Global score
Global enemycount
Global enemycountmax
Global Joyy#

// DEFINE TYPE TEMPLATES USING EXISTING USER-DEFINED TYPE METHOD
TYPE BulletType
 index
 image
 x
 y
 velocity
ENDTYPE

TYPE EnemyType
 index
 image
 x
 y
 velocity
 dir
 sound
 points
ENDTYPE

imgBullet = LoadImage ( ?bullet.png? )
imgEnemyShip = LoadImage ( ?enemy.png? )
imgPlayerShip = LoadImage ( ?player.png? )
sndShoot = LoadSound("laser.wav")
sndBoom = LoadSound("explode.wav")

player = CreateSprite (imgPlayerShip) 

do
	
	If enemycount<enemycountmax and Random(0,200)=100 then SpawnEnemy()
	If (GetPointerPressed() = 1) Then SpawnBullet() 
	UpdateBullets()
	UpdatePlayer()
	UpdateEnemy()
	CollisionCheck()

	Sync()
loop

// SPAWN BULLET
Function SpawnBullet()

        Playsound(sndShoot) 
	AddNew BulletType
		BulletType.index=CreateSprite(imgBullet)
		BulletType.image=imgBullet	
		BulletType.x=playerx
		BulletType.y=playery
		BulletType.velocity=2
	Push BulletType

EndFunction

// SPAWN ENEMY
Function SpawnEnemy()

	AddNew EnemyType
		EnemyType.index=CreateSprite(imgEnemyShip)
		EnemyType.image=imgEnemyShip	
		EnemyType.x=integer Random( 300, 700 )
		EnemyType.y=integer Random( 100, 500 )
		EnemyType.dir=Random (0,1)
                EnemyType.sound=sndBoom
                EnemyType.points=Random(100,300)
	Push EnemyType	

	enemycount=enemycount+1

EndFunction

// UPDATE BULLET TYPES
Function UpdateBullets()

	ForEach BulletType
		BulletType.x=BulletType.x+BulletType.velocity
		SetSpritePosition(BulletType.index,BulletType.x,BulletType.y) 
		if BulletType.x>800 then delete BulletType
	Next

EndFunction

// UPDATE ENEMY TYPES
Function UpdateEnemy()

	ForEach EnemyType
		if EnemyType.y<0 then EnemyType.dir=1 
		if EnemyType.y>600 then EnemyType.dir=0		
		if EnemyType.dir=1 then EnemyType.y=EnemyType.y+1
		if EnemyType.dir=0 then EnemyType.y=EnemyType.y-1
		SetSpritePosition(EnemyType.index,EnemyType.x,EnemyType.y)
	Next

EndFunction

// UPDATE PLAYER
Function UpdatePlayer()
	
	SetSpritePosition (player,50,GetPointery())
	

EndFunction

// CHECK FOR COLLISIONS BETWEEN BULLETS AND ENEMY TYPES
Function CollisionCheck()

	ForEach BulletType
		ForEach EnemyType
			if GetSpriteCollision(BulletType.index, EnemyType.index)
				score=score+EnemyType.points
                                PlaySound(EnemyType.sound)
				enemycount=enemycount-1
				Delete BulletType
				Delete EnemyType 		
			EndIf
		Next
	Next

EndFunction


Thank you.
Posted: 26th Oct 2011 1:12
As the idea behind Basic is to make commands obvious I would suggest "EndAdd" rather than "Push dataType"... I don't know what "Push" means from reading it. It fits in better with the language to me.

I like the idea of Dynamic Types a lot as it would simplify a lot of my code. I agree it fits in well with the language.

Just a 'Basic' programmer's perspective.
Posted: 26th Oct 2011 2:34
My only problem with that example is, what if you want more than one list? That groups all instances of the type together.

In C#, the foreach syntax is (simply put):

foreach(Type item in container)
{ <block> }

The container is any class that supports enumeration, such as a list or array. For AppGameKit I would think something like this would be nice:

+ Code Snippet
type Bullet
  x as integer
  y as integer
  alive as integer
endtype

// note no size
dim bullets[] as Bullet

function Shoot()
  newbullet as Bullet
  newbullet.x = 10
  newbullet.y = 10
  newbullet.alive = 1
  add bullets[], newbullet
endfunction

function Update()
  foreach current in bullets[]
    current.x = current.x + 1
    if current.x &gt; 50
      // no index removes current element from current foreach scope
      // otherwise Remove should require second parameter
      remove bullets[]
    endif
  next current


I wouldn't be 100% set on my syntax there (pseudo code is difficult on an iPad) but I think containers need to be independent from the type itself and the syntax should be consistent with the rest of the language.
Posted: 26th Oct 2011 3:15
@baxslash - Basically that is just saying that you are ready to push this object to the list. It makes more sense to me that way but I really don't care what the command is. The easier the better.

@Airslide - I originally suggested that method in my pseudo code a few posts above. In the example, I am obviously trying to keep the concept as simple as possible taking into account Lee's concerns. I assume Lee is a C++ programmer and probably already knows how it's done in that language.

Being able to have the system manage multiple lists offers more flexibility but for me, not an absolute deal-breaker as I can create multiple Type templates if I really needed to. You sort of run into that question of how to implement a powerful feature like this while keeping in mind that person who just picked up AppGameKit for the first time. I'm not advocating turning AppGameKit into a OOP language, I just want an easier way to manage my game assets than what is currently available. Dynamic Types in whatever incarnation they come in will certainly help.

Also as Lee mentioned, if you want the full meal deal there is always the Tier-2 option.
Posted: 26th Oct 2011 5:54
Personally I don't think it'd be too complicated, in fact having a list that they created could make it easier for a new user to grasp where their data is being stored. As it is right now they have to learn arrays, and lists seem a little more natural even.
Posted: 26th Oct 2011 12:37
I use Delphi all the time because I dislike C++. Delphi's iteration is very powerful and simple, and can work with almost any list type. It's implemented using the already existing keyword "in".

Here's a string example:
var
s: string;
c: char;

begin
s:=' Delphi Rocks!';
for c in s do //<--- here is the interesting part
begin
Application.MainForm.Caption:=Application.MainForm.Caption+c;
Sleep(400); //delay a little to see how it works
end;

Also works with dynamic lists, and easy to understand because it's just a special case of a for loop.
Posted: 27th Oct 2011 1:23
The problem I'm seeing for a foreach keyword though is that even in my example it looks dangerously close to using reference types. It could be confusing to users when their variables don't act the same way outside the loop.
Posted: 27th Oct 2011 7:01
Not sure I follow...
Posted: 28th Oct 2011 2:27
Understandable, I didn't really elaborate. Basically, the variable for the item in the foreach loop ("current" in my example) is a reference back to the element inside the array (bullet[current's index]). This doesn't really match up with the rest of the language. For example:

+ Code Snippet
type MyType
	a as integer
	b as integer
endtype

var1 as MyType
var2 as MyType

var1.a = 5
var2 = var1

Print(var1.a) // 5
Print(var2.a) // 5

var2.a = 2

Print(var1.a) // 5
Print(var2.a) // 2


That example should make perfect sense, since UDTs are essentially structs. When var2 is assigned to var1, var1's values are copied into var2, it does not become a pointer. If they were reference types:

+ Code Snippet
referencetype MyType
	a as integer
	b as integer
endtype

// some pseudocode since reference types don't actually exist in AGK
var1 as MyType : var1 = new MyType
var2 as MyType

var1.a = 5
var2 = var1 // var2 is a reference to var1

Print(var1.a) // 5
Print(var2.a) // 5

var2.a = 2

Print(var1.a) // 2 &lt;-- var1.a is also 2!
Print(var2.a) // 2


Now, the problem here is that the current item in the foreach loop looks a lot like that sort of reference. So somebody might be tempted to do this:

+ Code Snippet
foreach bullet in bullets[]
	MoveBullet(bullet)
next bullet

function MoveBullet(obj as BulletType)
	obj.x = obj.x + 1
endfunction


However, that won't work. 'bullet' in the foreach loop is a reference/pointer type to bullets['bullet''s index]. However, when we pass it as a parameter, we are just copying it into 'obj'. So we need the index in order to act on bullet in another scope, such as that of a function. This may be confusing and, for a large project, makes foreach more of a convenience for loops that are entirely self contained than something that can be used for entity management.

If the foreach loop treats the item variable like the rest of the language treats UDTs, then any modifications you make to it won't be saved back to the array, which diminishes its value a bit (but would be in line with how foreach on an array of structs works in C#).
Posted: 28th Oct 2011 14:22
I agree with airslide about this, but it's not an inherently difficult problem to solve. It's very simple and obvious in Pascal and C and has been for 30 years. All it needs is a pass by reference flag:

procedure NoRef(x : integer)
begin
// x is copied to this function and becomes a local variable
x:= x + 1; //increases the local variable but NOT the passed variable
end;

procedure ref(var x : integer)
begin
// x must be an actual variable, not a constant
x := x + 1; // the variable passed in x is changed
end;

With object orientation things become slightly muddied, because objects are always passed as dynamic and modifiable.

Hey ho!
Posted: 30th Oct 2011 5:11
The ref flag idea is a good one in my opinion, but Lee has previously expressed apprehension about pointers and reference types. Still, an explicit "ref" keyword seems easy enough to follow.
Posted: 30th Oct 2011 10:57
I agree. There's a significant difference between passing by reference and allowing an explicit pointer type which could be modified to point outside the sandbox. One advantage is that it removes the need for loads of global variables, which are regarded as bad programming practice.
Posted: 21st Nov 2011 20:19
Monkey has dynamic lists

+ Code Snippet
Public l as List&lt;type&gt; = new List&lt;type&gt;
l.AddLast(new type)

For t:type = EachIn l

Next


AGK could do something like that (imho)