Help creating more than one instance of an object?

BlitzMax Forums/BlitzMax Beginners Area/Help creating more than one instance of an object?

Templeman(Posted 2007) [#1]
Ok, I think I'm getting confused about something and I hope when someone replys it'll be what I need to move forward..

I want to create more than one instance of a pre-defined object, like a small rectangle.

For instance, say I want to create a starfield. Nothing fancy, just say 40 5x5 rectangles on the screen in random places but I don't want to make 40 drawrec commands with 40 sets of co-ordinates.

Can someone give me an example of this? As basic as possable?

I've seen it in a few tutorials but they all seem to gloss over what exactly they do, or they seem to be part of a bigger chunk of code, which I'm really having a great deal of trouble with. Either that or I'm missing it each and every time I look for it.

Help me out guys, I'm going nuts over this!!

Thanks! :)


H&K(Posted 2007) [#2]
for f=1 to 40
rectangle.draw(int rnd(0.0,799.0),int rnd(0.0,639.0))
next



Grey Alien(Posted 2007) [#3]
Strict

Const MAX_STARS=100

Const WIDTH = 800
Const HEIGHT = 600

Graphics WIDTH, HEIGHT ,0

Type TStar
	Field x
	Field y
	Field radius
	Field speed
End Type

Global StarList: TList = New TList

'make some stars
For Local i = 1 To MAX_STARS
	Local s:TStar = New TStar
	s.x = Rand(0,WIDTH)
	s.y = Rand(0,HEIGHT)
	s.radius = Rand(1,4)
	s.Speed = Rand(1,5)
	StarList.AddLast(s)
Next

While Not KeyHit(KEY_ESCAPE)
	Cls
	'Move and draw the stars
	For Local s:TStar = EachIn StarList
		s.x:+s.speed
		'wrap around
		If s.x>=WIDTH Then s.x:-WIDTH
		DrawOval s.x, s.y, s.radius, s.radius
	Next
	Flip 1	
Wend



Templeman(Posted 2007) [#4]
Ok Grey Alien, I think I sort of understand that, but what if I want to make a player shot? How would this translate into that?

I appreciate the help, I hope to god this sinks in. I keep thinking one day I'll see something that makes everything else fall into place like a moment of clarity!

Thanks again guys!


H&K(Posted 2007) [#5]
A player shot should have its own type, and either has one instance with a TList (or similar) of shots, or a new instance for each shot


Templeman(Posted 2007) [#6]
That's what I'm getting at. I understand that much, I just have no idea how the code would be arranged.

I tried to translate Grey Alien's code into a player shot, but I just get the one instance created. Here's what I did (please don't laugh, I'm crap!):


Type TPlayer
	Field x:Int=200
	Field y:Int=300
	Field speed

	Function UpdateState()
		If KeyDown(key_left) Then player.x:-4
		If KeyDown(key_right) Then player.x:+4
		If KeyDown(key_up) Then player.y:-4
		If KeyDown(key_down) Then player.y:+4
		If player.x <0 Then player.x=0
		If player.x >WIDTH-40 Then player.x=WIDTH-40
		If player.y <0 Then player.y=0
		If player.y >HEIGHT-20 Then player.y=HEIGHT-20
	End Function

End Type

Type TShot
	Field x:Int=Player.x
	Field y:Int=Player.y
	Field rate
	Field speed
	Field radius
End Type

Global ShotList: TList = New TList
Global Player:TPlayer = New TPlayer
Global StarList: TList = New TList

'make some stars
For Local i = 1 To MAX_STARS
	Local s:TStar = New TStar
	s.x = Rand(0,WIDTH)
	s.y = Rand(0,HEIGHT)
	s.radius = Rand(1,4)
	s.Speed = Rand(1,5)
	StarList.AddLast(s)
Next

'make some shots
For Local i = 1 To MAX_STARS
	Local sh:TShot = New TShot
	sh.radius = 4
	sh.Speed = 5
	ShotList.AddLast(sh)
Next

While Not KeyHit(KEY_ESCAPE)
	Cls
	'Move and draw the stars
	DrawRect(Player.x,Player.y,40,20)
	Player.UpdateState()
	For Local s:TStar = EachIn StarList
		s.x:-s.speed
		'wrap around
		If s.x<0 Then s.x=WIDTH
		DrawOval s.x, s.y, s.radius, s.radius
	Next
	If KeyDown(key_space)
		For Local sh:TShot = EachIn Shotlist
			sh.x:+sh.speed
			DrawRect sh.x,sh.y,sh.radius,sh.radius
		Next
	EndIf
	Flip 1	
Wend




I'm still (even after several months) very green to programming. I'm starting to wonder if my mind is capable of storing all I need to know. :(


H&K(Posted 2007) [#7]
You have lots of shots, they just all have the same position. (Also it should be 0 to maxshots)

Edit If you havent defined Maxstars you will only have one shot


Templeman(Posted 2007) [#8]
Max_Stars was defined by Grey Alien as 100 right at the top. I just used it since it was already defined. I could have just had any number in there.

I realise there is only one shot with only one position, I need to know how I can rectify the problem and understand it!

FYI, I'm brand new to coding in ANY language!


Templeman(Posted 2007) [#9]
Just to clarify, I need the shot to stay hanging around after I have released spacebar, create an additional shot every time I hit spacebar and cease to exist when it leaves the screen.

Oh, it'd be useful if it came from the ship too rather than the ship's initial position ;-)

And oh to have a laptop that didnt press buttons of it's own accord and have a trackpad that stops working for 30 secs every five minutes.. adding to my frustration slightly :-)


Grey Alien(Posted 2007) [#10]
Strict

Const MAX_STARS=100

Const WIDTH = 800
Const HEIGHT = 600

Graphics WIDTH, HEIGHT ,0

Type TStar
	Field x
	Field y
	Field radius
	Field speed
End Type

Type TShot
	Field x
	Field y
	Field radius
	Field speed
	
	Function Create:TShot(x,y)
		Local s:TShot = New TSHot
		s.x = x
		s.y = y
		s.radius = 5
		s.speed = 5
		ShotList.AddLast(s)
		Return s
	End Function
End Type

Type TPlayer
	Field x:Int=200
	Field y:Int=300
	Field w = 40
	Field h = 20
	Field speed = 4
	Field FireCounter = 0
	Field FireSpeed = 10

	Method UpdateState()
		If KeyDown(key_left) Then x:-speed
		If KeyDown(key_right) Then x:+speed
		If KeyDown(key_up) Then y:-speed
		If KeyDown(key_down) Then y:+speed
		If x < 0 Then x=0
		If x > WIDTH-w Then x=WIDTH-w
		If y < 0 Then y=0
		If y > HEIGHT-h Then y=HEIGHT-h
	End Method
End Type

Global StarList: TList = New TList
Global ShotList: TList = New TList
Global Player:TPlayer = New TPlayer

'make some stars
For Local i = 1 To MAX_STARS
	Local s:TStar = New TStar
	s.x = Rand(0,WIDTH)
	s.y = Rand(0,HEIGHT)
	s.radius = Rand(1,4)
	s.Speed = Rand(1,5)
	StarList.AddLast(s)
Next

While Not KeyHit(KEY_ESCAPE)
	Cls
	'Move and draw the stars
	SetColor 255,255,255
	For Local s:TStar = EachIn StarList
		s.x:-s.speed
		'wrap around
		If s.x<0 Then s.x:+WIDTH
		DrawOval s.x, s.y, s.radius, s.radius
	Next
	
	'draw player on top of stars
	SetColor 0,200,255
	DrawRect(Player.x,Player.y,Player.w, Player.h)
	Player.UpdateState()

	'make new bullets?
	If KeyDown(KEY_SPACE) And Player.FireCounter = 0 Then
		TShot.Create(Player.X+Player.w, Player.Y+(Player.h/2))			
		'Sset a counter going so the player can't fire again immediately.
		Player.FireCounter = Player.FireSpeed		
	EndIf
	'reduce firecounter, but only if active.
	If Player.FireCounter> 0 Then Player.FireCounter:-1
	
	'move and draw the bullets
	SetColor 255,50,50
	For Local s:TShot = EachIn ShotList
		s.x:+s.speed
		'wrap around
		If s.x>=WIDTH Then ShotList.Remove(s) 'kill the bullet
		DrawOval s.x, s.y, s.radius, s.radius
	Next
	SetColor 255,255,255 'restore colour
	
	Flip 1	
Wend
	


Notes:

- Shot has a Function to create new instances of itself and add to the ShotList.
- Player.UpdateState is now a Method so you don't have to put player. in front of all the coordinates and I used a speed field. Methods are not the same as Functions, read up about them.
- Beforehand you were creating a load of ready made shots, that's not the way to do it, you should have an empty list and add shots when fire is pressed, and delete them when they go off-screen.
- See how have I limited the firespeed.
- Player now has w (width) and h (height) fields.
- Really the Press Space detection should go in UpdateState.

Hope this helps, it was fun.


Templeman(Posted 2007) [#11]
Thanks for that, it did clear up most of my issues, one little thing though.

I don't understand the relationship between the spacebar being pressed (TShot.Create) and the shot being drawn:

	If KeyDown(KEY_SPACE) And Player.FireCounter = 0 Then
		TShot.Create(Player.X+Player.w, Player.Y+(Player.h/2))			
		'Sset a counter going so the player can't fire again immediately.
		Player.FireCounter = Player.FireSpeed		
	EndIf

	
	'move and draw the bullets
	SetColor 255,50,50
	For Local s:TShot = EachIn ShotList
		s.x:+s.speed
		'wrap around
		If s.x>=WIDTH Then ShotList.Remove(s) 'kill the bullet
		DrawOval s.x, s.y, s.radius, s.radius


If they are in two separate If conditionals, how does the second part of code get involked?

I'm going to read this over and over though untill it clicks. It's got to at some point.. right? :)

Thanks again for the great help and glad it was fun!

On a side note, has anyone had a look at the Sloan Kelly Beginners Guide Book? Is it any good?


Grey Alien(Posted 2007) [#12]
When space is pressed it creates a shot and adds it to the shotlist. But it's not drawn with that code it's just created *ready* to be drawn.

The For loop simply loops through the list of shots (if any). when you start the game, the list is empty so nothing is drawn. When you create one or more shots, it loops through them, moves each one, checks to see if it's off screen and should be destroyed (That's what the If s for), and then draws it. Take another look, it's nice and simple.


H&K(Posted 2007) [#13]
http://www.blitzbasic.com/Community/posts.php?topic=42519


Templeman(Posted 2007) [#14]
Not sure about nice and simple for my.. simple mind!

I think I get it now though, if I go over it enough it'll fall into place and hopefully stick in my head!

Can't thank you enough GA, thanks mate!


Grey Alien(Posted 2007) [#15]
you are welcome, just keep on practicing, and remember - keep it simple.